Help us understand the problem. What is going on with this article?

【php-fpm,nginx,mysql】docker-composeで開発環境を構築する

dockerで開発環境を構築する際の手順

お断り

エンジニアとしてまだまだ未熟なので、
色々と間違っている場合もあるかもしれませんので、その場合は、コメントなどでご指摘いただけると嬉しいです!
知識のブラッシュアップにご協力お願いします!

説明する技術

  • docker
  • docker-compose

dockerとは

dockerを使えば、自分のpcの中に仮想コンテナを作成できるよってツールです。他にも仮想環境構築のためのツールは存在しますが、dockerは手軽さがウリ!だと思っています!簡単に仮想環境作ったり、消したり、更新したりが可能です。こちらの記事など参照にしたのでよくわからない方は是非ご覧ください。今回はコマンドなどではdocker-composeを利用していますが、基盤はdockerです。

docker-composerとは

簡単に説明すると以下のイメージです。
dockerコンテナを操作する"docker"コマンドはdockerコンテナ一つ一つを操作するためのコマンドですが、"docker-compose"コマンドは複数のdockerコンテナの相関関係を定義し、一括操作するためのコマンドです。dockerコンテナの複数管理用コマンドって感じですね

 2020-06-22 18.38.25.png

ディレクトリ構成

関係ないファイルは表示していませんが基本的な構造はこんな感じです。一部フォルダ名とかは見やすいように修正してます。

Directory
PROJECT-NAME
├── Api
│   ├── docker-compose.yml
│   ├── docker-mysql
│   │   ├── Dockerfile
│   │   ├── conf
│   │   │   └── my.cnf
│   │   └── data
│   │        └── 'dbのデータファイル群(DBのスキーマ構造とかデータとかの自動で作られるファイル)'
│   ├── docker-nginx
│   │   ├── Dockerfile
│   │   └── nginx.conf
│   ├── docker-php
│   │   └── Dockerfile
│   └── project
│       └── ..
└── Front
    ├── Dockerfile
    ├── docker-compose.yml
    ├── docker-nginx
    │   ├── default.conf
    │   └── log
    └── project
        ├── ..

【Api側】Dockerfile

各dockerコンテナの設定ファイルです。

php-fpmのDockerfile

php側では、必要なphpのライブラリとかをinstallするコマンド書いてあげます。初心者目線でのポイントは、FROMで指定したdockerイメージのOSの種類に合わせたコマンドをしっかり調べて書くことです。今回は"php:7.3-fpm"というdockerhubで公開されているphp公式イメージのphp-fpmを使いました。どうやらこいつがDebian系だったので、Dockerfileの中でapt-getコマンドを使ってます。

Api/docker-php/Dockerfile
# 基盤のimageファイル選択(php公式イメージ)
FROM php:7.3-fpm
# コンテナを立ち上げるときにライブラリ・パッケージのアップデートとインストール
RUN apt-get update && apt-get install -y \
  vim \
  zip \
  unzip \
  iputils-ping \
  git \
  imagemagick \
  gcc \
  make \
  libpng-dev \
  libmcrypt-dev \
  libjpeg-dev \
  libfreetype6-dev \
  && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
  && docker-php-ext-install -j$(nproc) gd

# コンテナを立ち上げるときにPDOのインストール(API作成前のDB接続確認のためインストール)
RUN docker-php-ext-install pdo_mysql

# composerファイルのコピー(APIでLaravel使うので、composerの準備もしておく)
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# 作業ディレクトリの指定(dockerコンテナに接続した時どのディレクトリから開始するか)
WORKDIR /var/www/html/project

nginxのDockerfile

nginx公式イメージを使用しました。vimとかunzipとか必要そうなミドルウェアを追加してます。

Api/docker-nginx/Dockerfile
# 基盤のimageファイル選択(nginx公式イメージ)
FROM nginx:1.17.9
# コンテナを立ち上げるときにパッケージのアップデートとインストール
RUN apt-get update && apt-get install -y \
  vim \
  unzip \
  zip \
  git

# 作業ディレクトリの指定
WORKDIR /var/www/html

mysqlのDockerfile

ここでは特に指定せず。mysqlの設定ファイルを別で作成しました。イメージはmysql公式イメージを利用しました。

Api/docker-mysql/Dockerfile
# 基盤のimageファイル選択
FROM mysql:8.0.19

【Front側】Dockerfile

ここもApi側と一緒ですね。ApiとFrontでwebサーバを分けたのはマイクロサービス化したかったからです!あんまりわかっていないですが!一緒でもよかったのかなとか後から思いました。

Front/Dockerfile
# -----------------------------------------------------------------
# Nginx
# -----------------------------------------------------------------
# 基盤のimageファイル選択
FROM nginx:1.17.9
# コンテナを立ち上げるときにパッケージのアップデートとインストール
RUN apt-get update && apt-get install -y \
  vim \
  unzip \
  zip \
  git

【Api側】docker-compose.yml

Api/docker-compose.yml
version: "3"

services:
    # webサーバ用コンテナ設定
    web:
        # 元となるDockerfileのディレクトリ
        build: ./docker-nginx
        # コンテナ名を明示的に指定する
        container_name: API_Web_Container
        # 他コンテナとの依存関係(コンテナ起動の順番にも関係)
        depends_on:
            - app
        ports:
            - 80:80
        # マウントするホスト側ディレクトリ:マウント先コンテナディレクトリ
        volumes:
            - ./project/lib:/var/www/html/project
            - ./docker-nginx/nginx.conf:/etc/nginx/conf.d/default.conf
        # 他サービスとの接続
        links:
            - app
        # 継続起動のため
        tty: true
    # アプリケーションサーバ設定
    app:
        # 元となるDockerfileのディレクトリ
        build: ./docker-php
        # コンテナ名を明示的に指定する
        container_name: App_Container
        # 他コンテナとの依存関係(コンテナ起動の順番にも関係)
        depends_on:
            - db
        # 他サービスとの接続
        links:
            - db
        # マウントするホスト側ディレクトリ:マウント先コンテナディレクトリ
        volumes:
            - ./project/lib:/var/www/html/project
        # 継続起動のため
        tty: true
    # DBサーバ設定
    db:
        # 元となるDockerfileのディレクトリ
        build: ./docker-mysql
        # コンテナ名を明示的に指定する
        container_name: DB_Container
        ports:
            - 3306:3306
        # DBの変数設定
        environment:
            MYSQL_ROOT_PASSWORD: XXXXX #ここにroot用のパスワードを記載
            MYSQL_DATABASE: XXXXX #ここにデータベースを記載
            MYSQL_USER: XXXXX #ここにユーザ名を記載
            MYSQL_PASSWORD: XXXXX #ここにユーザ用パスワードを記載
        # マウントするホスト側ディレクトリ:マウント先コンテナディレクトリ
        volumes:
            # mysqlの設定ファイルをコンテナにマウント(ミラーリング的な?)
            - ./docker-mysql/conf:/etc/mysql/conf.d
            # 永続化するときにマウントするdir
            - ./docker-mysql/data:/var/lib/mysql

【Front側】docker-compose.yml

Front/docker-compose.yml
version: '3'

services:

 # webサーバ用コンテナ設定
 front:
    # 元となるDockerfileのディレクトリ
    build: .
    # コンテナ名を明示的に指定する
    container_name: Front_Web_Container
    ports:
        - 8080:8080
    # 継続起動のため
    tty: true
    networks: 
        - api_default
    # マウントするホスト側ディレクトリ:マウント先コンテナディレクトリ
    volumes:
        - ./docker-nginx/log/:/var/log/nginx/
        - ./project/build:/var/www/html/project
        - ./docker-nginx/default.conf:/etc/nginx/conf.d/default.conf
# APIのネットワーク名
networks: 
 api_default: // APIとFRONTのdockerコンテナ群をつなげるネットワーク
    external: true

dockerコンテナのビルド(*設計図に変更がなければ初回だけでOK)

dockerコンテナの*設計図(Dockerfileとdocker-compose.yml)を元に仮想コンテナを作成する。
docker-compose.ymlがある階層で以下のコマンドを実行します。ビルドがうまく行かない場合は各Dockerfileを見直してください。 2020-06-29 18.45.58.png

$ docker-compose build --no-cache    // --no-cacheはオプション

ビルドしたコンテナの起動

dockerコマンドと違ってportの指定など細かい設定をコマンドで記載する必要がないのがdocker-composeのいいところ!docker-compose.ymlがある階層で以下のコマンドを実行します。

$ docker-compose up -d

doneで起動成功していたらOK、失敗したらエラーメッセージを確認して見てください。

pc-user@pc-name api % docker-compose up -d
Starting DB_Container ... done
Starting App_Container ... done
Starting API_Web_Container ... done

起動がうまく行かない場合はdocker-compose.ymlを見直してください。

起動確認

コンテナが正常に起動できるか確認します。docker-compose.ymlがある階層で以下のコマンドを実行します。

$ docker-compose ps
pc-user@pc-name api % docker-compose ps
  Name               Command                         State   Ports
------------------------------------------------------------------------------------
App_Container       docker-php-entrypoint php-fpm   Up      9000/tcp
DB_Container        docker-entrypoint.sh mysqld     Up      0.0.0.0:3306->3306/tcp, 33060/tcp
API_Web_Container   nginx -g daemon off;            Up      0.0.0.0:8086->80/tcp

テーブル構造見やすいですね〜
StateがUp以外の場合は、起動後コンテナが停止してしまっているので継続起動の設定部分を確認してみてください。

API側でdocker-composeコマンドでコンテナをビルド・起動した場合はこのような結果となります。全てのコンテナが起動し、停止していなかったらOKです!問題が起こった場合は、docker-compose logsコマンドなどで原因を調査して、解決してください。

いい感じに起動したら最後に、、、!

dockerコンテナに接続

$ docker-compose exec app bash //appの部分はdocker-compose.ymlで定義したサービス名を入力
$ docker-compose exec web bash //appの部分はdocker-compose.ymlで定義したサービス名を入力
$ docker-compose exec db bash  //appの部分はdocker-compose.ymlで定義したサービス名を入力

念のため、3つのコンテナにそれぞれ接続するコマンドを記載しました。例として、DBに接続したい場合は、直接dockerコンテナに接続して、mysql -u -root -p(DBの種類に合わせて変更してください)と入力するか、GUIでDBに接続するツール等で127.0.0.1のIPと3306のポートを指定してあげれば大丈夫です!

 2020-06-29 18.45.58.png

補足

上記のdocker-compose.ymlファイルの場合、API側のdockerコンテナ起動→Front側のコンテナ起動の順番で行ってください!理由は、ネットワークの構築をAPI側で行っているからです。もしFront側を先にdocker-compose upしようとすると、「ネットワークがないよ」と怒られるのでご注意ください。

終わりに

ここまで、自分のPC内でdocker,docker-composeを使って環境構築する例を記載しました!
自分は環境構築に2週間くらいかかった感じですが、初心者すぎました!笑

ある程度エンジニアとして働いているかたはさらっと3日以内でできると思いますのでぜひdockerを使ってみてください!

以上、手軽に開発環境が構築できるdocker大好きマンでした!

k-yabiku
2018/01~プログラム勉強開始。技術はあまり好きじゃないけど新しいことが好きです! 浅く広く技術に触れているので理解が浅いのが悩み。記事書いて理解深めます! php,Laravel,Ruby,Ruby onRails,AWS,docker,dart,Angular dart,Xcode,Xamarin
protosolution
プロトソリューションは、Web制作・Webデザイン・デザイン制作・コールセンター・データ入力・ITインテグレーションとトータルでお客様のニーズにお応えする会社です
http://www.protosolution.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした