背景
AWSでの本番環境構築にむけてポートフォリオ開発を進めていたところ、以前の開発環境が簡易的で必要な設定がされておらず、環境依存が起こってしまう可能性が高いと考えたので、本番環境構築前に整えておこうという目的で再構築しました。
今回は再構築、初構築両方に対応できるように手順を記載しました。
状況に応じて実行、スキップします。
- GitHubリポジトリ
開発環境について
前提条件
- Dockerインストール済み
- VScodeインストール済み(Vimでも大丈夫です)
開発環境
- OS : Mac
- Docker 20.10.12
- Docker Compose v2.2.3
- Docker image
- laravel-app(appコンテナ)
- php7.4-fpm-alpine(nginx,php-fpm,supervisor)
- Laravel 6.20.34
- laravel-db(mysqlコンテナ)
- MySQL 8.0.27
- laravel-app(appコンテナ)
- Docker image
開発環境ディレクトリ構成
.
├── app
│ ├──nginx
│ │ ├──dev.ドメイン名.conf
│ │ └──nginx.conf
│ ├──php
│ │ ├──config.inc.php
│ │ ├──php-fpm.conf
│ │ ├──php.ini
│ │ └── www.conf
│ ├──supervisor
│ │ ├──app.conf
│ │ └──supervisord.conf
│ └──Dockerfile
├──mysql
│ ├──Dockerfile
│ └──my.cnf
└──docker-compose.yml
開発環境構成図
構築手順(サマリー)
手順 | 説明 |
---|---|
ディレクトリ作成 | ホームディレクトリにgit/githubディレクトリを作成 |
git clone | 作業ディレクトリに元の開発環境をgit cloneする ※初めて構築する場合はスキップ |
作業ディレクトリ作成 | git/github配下に作業ディレクトリを作成 ※初めて構築する場合のみ実行 |
LEMP環境設定 | appコンテナ,mysqlコンテナ,docker-compose.ymlの設定 |
docker run | コンテナの構築と起動 |
Laravel install | appコンテナに入り、Laravelのインストールを行います ※初めて構築する場合のみ実行 |
app deploy | appコンテナ内でcomposer install, マイグレーション(初めて構築する場合はスキップ)など実行 |
Access | 設定したドメイン名でアクセス確認 |
DB login | MySQLにログインできることを確認 |
Vue.js install | ※Vue.jsを使用する場合に実行 |
構築手順
ディレクトリ作成
- git/github配下に開発環境を構築します。
- git/github配下に移動
$ mkdir -p ~/git/github
$ cd ~/git/github
git clone
初めて構築する場合はスキップ
- GitHubリポジトリをcloneする。
- クローンしたディレクトリに移動
$ git clone リモートリポジトリURL
$ cd クローンしたディレクトリ
作業ディレクトリ作成
初めて構築する場合のみ実行
- git/github配下に任意のディレクトリを作成。
このディレクトリで開発をしていきます。 - 作成したディレクトリに移動
$ mkdir 任意のディレクトリ名
$ cd 作成したディレクトリ
LEMP環境設定
docker/devディレクトリ作成
- docker/devディレクトリ作成
- docker/dev配下に移動
$ mkdir docker
$ mkdir docker/dev
$ cd docker/dev
各ディレクトリ, docker-compose.yml作成
- app, mysqlディレクトリ作成
- docker-compose.yml作成
$ mkdir app mysql
$ touch docker-compose.yml
appコンテナ設定
- appディレクトリに移動
- nginx, php, supervisorディレクトリ作成
- Dockerfile作成
$ cd app
$ mkdir nginx php supervisor
$ touch Dockerfile
nginx設定
- nginx配下に移動
- dev.ドメイン名.conf, nginx.conf作成
$ cd nginx
$ touch dev.ドメイン名.conf nginx.conf
- dev.ドメイン名.conf設定
server {
listen 80;
server_name dev.ドメイン名;
root /var/www/app/public;
index index.php index.html index.htm;
access_log /var/log/nginx/dev.access.log main;
error_log /var/log/nginx/dev.error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
}
設定ファイル内の説明
設定 | 説明 |
---|---|
server{} | バーチャルホスト定義 |
listen 80; | 使用するポート指定 |
server_name | 使用するホスト名(ドメイン名を指定) |
root /var/www/app/public; | 公開するディレクトリ指定 |
index index.php index.html index.htm; | index.phpというファイルが存在すれば、"/public/index.php"に内部リダイレクト。 index.phpが在せず、index.htmlが存在すれば、/public/index.phpに内部リダイレクト。 |
access_log /var/log/nginx/dev.access.log main; | エラーログの出力先を設定 |
error_log /var/log/nginx/dev.error.log; | アクセスログの出力先を設定 |
location / {} | リクエストされたURIにマッチししたときに使われる設定。 設定は{}内に書く |
try_files $uri $uri/ /index.php?$query_string; | $urlにファイルがあるか、そしてディレクトリがあるかの確認。なければ/index.php$query_string へ内部リダイレクトする |
location ~ .php$ {} | location ~ .php$の設定に従い、php-fpmを経由してLaravelの開始スクリプトのindex.phpが実行される |
location ~ .php$ {}内の設定については以下記事の説明が参考になります
- nginx.conf設定
include /etc/nginx/conf.d/*.conf;で先程設定したdev.ドメイン名.confを読み込んでいます。
通常はnginx.confに直接書き込みますが、複数のバーチャルホストの設定を仮定してファイルを分割しました
user root;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '[nginx]\t'
'time:$time_iso8601\t'
'server_addr:$server_addr\t'
'host:$remote_addr\t'
'method:$request_method\t'
'reqsize:$request_length\t'
'uri:$request_uri\t'
'query:$query_string\t'
'status:$status\t'
'size:$body_bytes_sent\t'
'referer:$http_referer\t'
'ua:$http_user_agent\t'
'forwardedfor:$http_x_forwarded_for\t'
'reqtime:$request_time\t'
'apptime:$upstream_response_time\t';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
gzip on;
gzip_static on;
gzip_http_version 1.0;
gzip_disable "msie6";
gzip_proxied any;
gzip_min_length 1024;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
open_file_cache max=100000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
proxy_buffer_size 32k;
proxy_buffers 50 32k;
proxy_busy_buffers_size 32k;
include /etc/nginx/conf.d/*.conf;
}
PHP設定
- php配下に移動
- config.inc.php, php-fpm.conf, php.ini, www.conf 作成
$ cd ../php
$ touch config.inc.php php-fpm.conf php.ini www.conf
以下のファイル設定についてはかなりの文字数となるため掲載は諦めました。
私のポートフォリオの設定ファイルがそれになります。
ご参考までに。
- config.inc.php
- php-fpm.conf
- php.ini
- www.conf
supervisor設定
- supervisor配下へ移動
- app.conf, supervisord.conf作成
- app.conf, supervisord.conf設定
Supervisorでnginx(webサーバー)とphp-fpm(アプリの起動)の起動プロセスを一括管理しています。
$ cd ../supervisor
$ touch app.conf supervisord.conf
[supervisord]
nodaemon=true
[program:app]
command=/usr/local/sbin/php-fpm -F
autorestart=true
stopsignal=TERM
user=root
directory=/var/www/app/
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:nginx]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
stopsignal=TERM
user=root
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[unix_http_server]
file=/run/supervisord.sock
[supervisord]
logfile=/var/log/supervisord.log
loglevel=info
pidfile=/var/run/supervisord.pid
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///run/supervisord.sock
[include]
files = /etc/supervisor.d/*.ini
files = /etc/supervisor/conf.d/app.conf
Dockerfile設定
FROM php:7.4-fpm-alpine
ENV APP_ROOT /var/www/app
WORKDIR $APP_ROOT
# Setup UTC+9
RUN apk --update add tzdata && \
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
apk del tzdata && \
rm -rf /var/cache/apk/*
# install packages
RUN apk update && \
apk upgrade && \
apk add --update --no-cache \
autoconf \
bash \
build-base \
curl-dev \
freetype-dev \
g++ \
gcc \
git \
libjpeg-turbo-dev \
libpng-dev \
libxml2-dev \
libxslt-dev \
make \
mysql-dev \
mysql-client \
nginx \
openssh \
openssl \
py3-pip \
sudo \
supervisor \
tzdata \
vim \
redis \
yaml-dev \
zlib-dev
RUN docker-php-ext-install pdo_mysql soap
RUN docker-php-ext-configure gd \
--with-freetype=/usr/include/ \
--with-jpeg=/usr/include/ && \
NPROC=$(grep -c ^processor /proc/cpuinfo 2>/dev/null || 1) && \
docker-php-ext-install -j${NPROC} gd
# Install awscli
RUN pip install awscli
# PHP
RUN rm -f /usr/local/etc/php-fpm.conf.default
RUN rm -f /usr/local/etc/php-fpm.d/zz-docker.conf
COPY php/php-fpm.conf /usr/local/etc/php-fpm.conf
COPY php/php.ini /usr/local/etc/php/php.ini
COPY php/www.conf /usr/local/etc/php-fpm.d/www.conf
# Install xdebug
RUN pecl install xdebug redis
RUN docker-php-ext-enable xdebug
# composer install
RUN curl -sS https://getcomposer.org/installer | php -- --version=1.9.1 --install-dir=/usr/bin
RUN mv /usr/bin/composer.phar /usr/bin/composer
# install Node.js
COPY --from=node:14.2 /usr/local/bin /usr/local/bin
COPY --from=node:14.2 /usr/local/lib /usr/local/lib
## nginx
ADD nginx/nginx.conf /etc/nginx/nginx.conf
ADD nginx/dev.ドメイン名.conf /etc/nginx/conf.d/dev.ドメイン名.conf
# setting superviser
COPY supervisor/supervisord.conf /etc/supervisord.conf
COPY supervisor/app.conf /etc/supervisor/conf.d/app.conf
RUN echo files = /etc/supervisor/conf.d/*.conf >> /etc/supervisord.conf
EXPOSE 80
CMD ["/usr/bin/supervisord"]
設定 | 説明 |
---|---|
FROM | ベースイメージ。php:7.4-fpm-alpine |
ENV | 環境変数 |
WORKDIR | 指定したディレクトリでWORKDIR以下の命令が実行される。今回はENVで定義されたAPP_ROOT(=/var/www/app) |
RUN | 実行コマンド |
ADD | ファイルを追加する命令 |
EXPOSE | コンテナ実行時にリッスンするポートやプロトコルをDockerに通知する命令。 |
CMD | コンテナの初期設定の命令。Dockerfileの中で1つだけ指定できる。 複数書いた場合は最後に書いたものが実行される。 supervisordを指定し、管理対象ファイルを実行。 |
MySQLコンテナ設定
- mysql配下に移動
- Dockerfile, my.cnf作成
- Dockerfile, my.cnf設定
$ cd ../../mysql
$ touch Dockerfile my.cnf
FROM --platform=linux/x86_64 mysql:8.0.27
ENV TZ Asia/Tokyo
ENV LC_ALL ja_JP.UTF-8
ENV MYSQL_ALLOW_EMPTY_PASSWORD yes
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 467B942D3A79BD29
RUN apt-get update
RUN apt-get install -y --no-install-recommends\
locales \
python \
vim \
&& apt-get clean \
&& rm -rf /var/cache/apt/archives/* \
/var/lib/apt/lists/*
RUN echo "ja_JP.UTF-8 UTF-8" > /etc/locale.gen && \
locale-gen ja_JP.UTF-8
# Setup MySQL
RUN touch /var/log/mysqld.log \
&& chown mysql:adm /var/log/mysqld.log
RUN mkdir /var/mysql \
&& chown mysql:adm /var/mysql \
&& rm -rf /etc/mysql/conf.d
COPY ./my.cnf /etc/mysql/
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
disable_log_bin
log-error=/var/log/mysqld.log
character_set_server=utf8mb4
collation-server=utf8mb4_bin
default-authentication-plugin = mysql_native_password
default-time-zone='+9:00'
innodb_file_per_table=ON
innodb_buffer_pool_size=4G
#innodb_log_file_size=1G
join_buffer_size=256K
read_buffer_size=1M
read_rnd_buffer_size=2M
sort_buffer_size=4M
max_heap_table_size=16M
tmp_table_size=16M
thread_cache_size=100
wait_timeout = 86400
max_allowed_packet = 1G
innodb_buffer_pool_size = 1G
max_allowed_packet = 16M
innodb_strict_mode = 0
long_query_time = 5
sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
[mysql]
default-character-set=utf8mb4
docker-compose.yml設定
- dev配下に移動
- docker-compose.yml設定
$ cd ../
version: '2'
services:
app:
container_name: アプリ名-app
build: ./app/
image: アプリ名-app
ports:
- '80:80'
volumes:
- ~/git/github/アプリのディレクトリ名:/var/www/app:delegated
tty: true
depends_on:
- db
db:
container_name: アプリ名-db
build: ./mysql/
image: アプリ名-db
command: --default-authentication-plugin=mysql_native_password
ports:
- '3306:3306'
environment:
MYSQL_DATABASE: アプリのディレクトリ名
volumes:
- ./mysql/db_data:/var/lib/mysql
設定 | 説明 |
---|---|
version | Composeファイルのバージョン。参考:公式サイト |
services | サービスの指定。サービス名:app, db |
container_name | コンテナ名:アプリ名-app, アプリ名-db(分かりやすい名前が無難) |
build | サービスをビルドする。Dockerfileを使ってDockerイメージを構築 |
image | イメージ名:アプリ名-app, アプリ名-db |
ports | ローカル(ホスト)側とDockerコンテナ側のポート番号の関連付け ローカルの80番ポートとNginxコンテナの80番ポートをマッピングしている。 |
environment | 環境変数 |
volumes | ローカルとDockerコンテナ間のディレクトリのリソースを関連付ける設定 |
tty | コンテナを起動し続ける設定 |
depends_on | コンテナの起動順。DBコンテナから起動するように設定 |
環境変数の設定
初めて構築する場合はスキップ
- アプリのディレクトリへ移動
- .envの作成、環境変数の設定
$ cd ~/git/github/アプリのディレクトリ名
$ cp .env.example .env
// 作成した.envの設定をする
docker run
- docker/dev配下へ移動
- コンテナの構築と起動
- コンテナの起動を確認
$ cd docker/dev
$ docker-compose up -d
$ docker-compose ps
Laravel install
初めて構築する場合のみ実行
- appコンテナに入る
- Composerインストール
- Composerバージョン確認
- Laravelインストール
- Laravelのディレクトリやファイルを確認
- .env作成、環境変数の設定
- APP_KEY生成
- .envの更新反映
- app再起動
$ docker exec -it appコンテナ名 bash
# composer install
# composer -V
# composer create-project --prefer-dist "laravel/laravel=6.*" .
# ls
# cp .env.example .env
// 作成した.envの設定をする
# php artisan key:generate
# php artisan config:cache
# /usr/bin/supervisorctl restart app
app deploy
初めて構築する場合はスキップ
- appコンテナに入る
- Composerインストール
- Composerバージョン確認
- APP_KEY生成
- .envの更新反映
- マイグレーション
- app再起動
$ docker exec -it appコンテナ名 bash
# composer install
# composer -V
# php artisan key:generate
# php artisan config:cache
# php artisan migrate
# /usr/bin/supervisorctl restart app
- gitignore修正
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
.env
.env.backup
.phpunit.result.cache
docker-compose.override.yml
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
/docker/dev/mysql/db_data
Access
- /etc/hosts編集
$ sudo vim /etc/hosts
127.0.0.1 dev.ドメイン名 に変更
-
http://dev.ドメイン名/
にアクセスしてアプリ(又はLaravelウェルカムページ)の表示確認できたら完成
再構築の場合
DB login
-appコンテナに入る
- 最後にMySQLログイン確認
$ docker exec -it appコンテナ名 bash
# mysql -u root -h db -p
Vue.js install
※Vue.jsを使用する場合に実行
- appコンテナに入る
- npmバージョン確認
- npmがinstallされてない場合は以下手順
- npm インストール
- npmバージョン確認
- Vue.sインストール
$ docker exec -it appコンテナ名 bash
# npm -v
// npmがinstallされてない場合は以下手順
# npm install
# npm -v
# npm install -D vue
# npm install -D vue-template-compiler
振り返り
Dockerひとつとっても様々な構築手順があるんだなぁと感じました。
まだまだnginx, php-fpmなどの設定に関する知識が乏しいので、これから深く学習していきます!!
やはりDockerを使用した環境構築は速くて便利!! 自由自在に構築できるようになりたいですね。
参考