2024
01.31 Wed.
2024
01.31 Wed.
みなさん、こんにちは!
初回投稿に続きまして、情報システム課の川部 です。
入社して、約2ヶ月が経とうとしています。最近は外の気温も一気に下がったような気がしますよね。気温の変化に乾燥と体調を崩しやすい季節ですが、まずは元気に頑張っていこうと思います!
さて本日は2回目の投稿ということで、ローカルにLaravel×DockerでWebサーバー用開発環境を構築したことについて触れていきます。
環境構築、というとエンジニアにとってみれば出来て当たり前。けど、独学では元々環境が一式揃ってるアプリに頼ったり理解まで頭を回さず「動けばよし」の精神で動かしていたり・・・。当然ながら初めての構築で散々迷いましたが、今回はDockerを使ったLaravelの環境構築の際に気づいたこと・学んだことについてまとめさせていただきます。
そもそもdockerとはなんなのか。何度も耳にはしていましたが、実際に使ったことはないDocker。知っていることはコンテナサービスという事と、クジラのマークということくらい。
ということで、今回はdockerについての概要と、dockerを使ってコンテナが起動できるまでの流れを自分なりにまとめたいなと思います。そんなの当然のように知ってる、という方もひよっこの備忘録だと思ってお付き合いしてくれると嬉しいです。
Dockerはホストマシンの中に完全に隔離された場所(コンテナ)を作ってアプリケーションなどを開発できるプラットフォーム。だそうです。
これを利用することで、元々のPCの環境に影響を与えることなく環境を構築したり、コンテナごとデプロイできるとのこと。
ちなみに大きなクジラの背中に箱がコンテナみたいです。コンテナは上でも少し触れたPC上で隔離された箱のようなものであり、Dockerを使うことでOSの管理をすることなく自分のPCにポンと環境を作れちゃいます。(ただし、他のコンテナを動かすには作ったコンテナとOSが同じじゃないといけません。)
以下は自分が確認用に作った図です。
四角い箱がコンテナのイメージです。こんな感じで箱の中に色々詰め込んでおけるんですよね。
しかもです。コンテナは独立しているため異なる環境を簡単に複数作って用意できますし、設計図さえあればチーム全員に同じ箱の作り方を共有することもできます。Dockerは便利、とはチラホラ聞いていましたが先端に触れて使ってみるだけもとても便利なことがわかります。(便利な仕組みを考え、作れる方は本当にすごいですよね。)
dockerについてわかったところで、環境構築の方に進んでいきます。
まずは作りたい環境について簡単に整理。今回は、Webサイトを作るという想定でWeb サーバ・アプリケーション・データベースの三つのコンテナを作ります。フレームワークはLaravelを使い、以下のコンテナとディレクトリの構造で環境構築します。(ディレクトリの構造もよくわからず、Gitで色々みて構成を決めてみました。)
構築するコンテナ
Web サーバ: Nginx
データベース: MySQL
アプリケーションサーバー: php-fpm
ディレクトリの構造
web-site/
├──app
│
├──boostrap
.
.
.
├── docker/
│ ├── db/
│ │ └── my.cnf
│ ├── nginx/
│ │ └── default.conf
│ └── php/
│ ├── Dockerfile
│ └── php.ini
├── docker-compose.yml
└── .env
このように、Web サーバ・アプリケーション・データベースを組み合わせた環境を3層アーキテクチャと言ったりするそうです。言葉だけだと頭の中に中々入らないので、整理するために簡単に図にしてみます。
こんな感じで三つに役割を分けることでわかりやすい構造していく、といったものです。(ちなみに、アプリーケーションサーバの中で三層に分けるのも3層アーキテクチャと呼ぶらしいです。そこから更にModel、View、Controllerの三つに分けるMVCモデルというものあります。この辺りはLaravelを使う上でも必要な知識になりそうですが勉強中のため、いつか記事にまとめたいですね。)
では、早速 Dockerで環境を作っていきたいのですが・・・。
構築するには元となるDockerイメージというものが必要で、更にそのDockerイメージの設定図が必要とのこと。
更にさらに、その設計図となるのがDockerfileです。このDockerfileがコンテナの元になるDockerイメージの設計図のような役割です。正直この時点で必要なものがいっぱいで、僕の頭は大いに混乱してました。
それを助けてくれるのが、複数のコンテナをまとめて管理してくれるdocker compose。
なんと基本的に複数のコンテナを起動する際にはdocker-compose.ymlからイメージを作成し起動してくれます。
初めてDockerを触った僕でも、このファイルを見ればどんなコンテナを作ってくれるのか「わかる」ということは理解できます。見てすぐわかる、というのは他の人と協力するのにも大切なことですからまとめてくれると助かりますよね。(本当にわかりやすい、ということがどれだけ大切か身に沁みます。)
またまた、自分の整理のため軽くまとめです。
Dockerfile:Dockerイメージの設計図。どんなコンテナを作りたいか記載するところ
Dockerイメージ:コンテナを動作させるのに必要なテンプレート
docker-compose:複数のコンテナをまとめて管理してくれる便利機能
そして、以下が今回使用した「docker-compose.yml」の中身になります。ここからはコンテナが動くのに必要なファイルを一気に乗っけていきたいと思います!
(なお、今回は初めてのdocker構築だったので色々コメントをつけて見返せるようにしてあります。設定ファイルで何をしているか調べながら記事を書くことで、なんとなく動かしている状況から一歩だけ前進できた気がします。)
web-site/ docker-compose.yml
今回は、上記で説明したWeb サーバ・アプリケーション・データベースの三つのコンテナを作るため「web_php」「web_nginx」「web_db」という名前でコンテナを作っていきます。
version: '3.9'
services:
# コンテナ名、Dockerfileの読み込み、コンテナのデータを保存する場所を設定。
php:
container_name: web_php
build:dockerfile: ./docker/php/Dockerfile
volumes:
- ../:/var/www
# DBが起動してからWebサーバを起動
depends_on:
- db
nginx:
# バージョンの指定
image: nginx:1.25.0
container_name: web_nginx
# 使うポートの指定
ports:
- "8000:80"
volumes:
- ../:/var/www
# default.confの反映
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
working_dir: /var/www
depends_on:
- db
db:
image: mysql:8.2
container_name: web_db
# 環境変数(任意の値を入力)
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: 任意のDB名
MYSQL_USER: user
MYSQL_PASSWORD: docker
TZ: 'Asia/Tokyo'
volumes:
- ./docker/db/data:/var/lib/mysql
- ./docker/db/conf:/etc/mysql/conf.d
- ./docker/db/sql:/docker-entrypoint-initdb.d
- ./docker/db/logs:/var/log/mysql
ports:
- "3306"
主な設定は以下になります。
①container_name
そのままコンテナの名前になります。DBのホストなどにも設定する名前なのでわかりやすいのが良いかなと思います。今回は上にも書いてある通り「web_php」「web_nginx」「web_db」という名前で作成しました。
②image
コンテナで起動するイメージです。バージョンの指定などもできます。dockerfileから起動する場合は「build」でdockerfileのパスを指定してあげます
③volumes
ボリュームをマウントする場所を指定します。コンテナ内のデータをホストマシンやDockerのボリュームに保存することでコンテナが落ちた時にもコンテナ内の内容を保持しておけます。
④ports
ポート番号の指定です。指定する形式は「ホストマシンのポート番号:コンテナのポート番号」となります。
⑤working_dir
作業ディレクトリを指定できます。
⑥depends_on
依存関係を定義してくれます。今回はDBの起動を確認してからPHPの起動を行います。
こちらのファイルが用意できたら、そのほかに必要なファイルも用意してきます。
DockerFile
まずはphpを使う上で事前に準備しておいたり、入れておきたいものをカスタムしてくれるDockerFileを作ります。
ちなみに初めて作った時は、ここにcomposer
を設定していなかったためコンテナを起動した後composer
を直接入れる・・・ということをしてました。しっかり設定することで他の人とGitなどで共有した時に僕のように一個一個コンテナを立ててから悩んだり操作する必要もないため、絶対必要なものは入れておかないともったいないですよね。
ここを見ればアプリケーションサーバーに入ってるものがすぐわかって、管理も簡単なのだと頭の中にメモしておきます。
FROM php:8.2-fpm
# このphp.iniファイルをコンテナ内の/usr/local/etc/php/ディレクトリにコピー
COPY php.ini /usr/local/etc/php
# パッケージのインストール
RUN apt-get update
RUN apt-get -y install libzip-dev
RUN docker-php-ext-install zip
RUN docker-php-ext-install zip pdo_mysql
RUN apt-get -y install cron
# composerをインポート
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin
WORKDIR /var/www/プロジェクト名
# Laravelのインポート
RUN composer global require "laravel/installer"
今回はコンテナ起動時にapt-get
をupdateした後にcomposer
を使えるようにインポート。そのcomposer
を使ってフレームワークであるLaravelをインストールしています。
php.ini
続けて、phpの環境設定ファイルであるphp.iniを作ります。
こちらでは、文字コードだったり言語設定だったりの設定をすることができます。おおまかな設定内容はコメントに書いてみました。
(タイムゾーンなど設定し忘れるとログファイルなどを後から見たときに変な時間で一瞬頭を傾げことに。文字化けなんかも起こりうるし、実体験が伴うと設定の大切さがわかりますよね・・・。)
# 文字コードをUTF-8に設定
default_charset = UTF-8
# タイムゾーンを東京に設定
[Date]
date.timezone = Asia/Tokyo
# メモリ統計情報の収集
[mysqlnd]
mysqlnd.collect_memory_statistics = on
# Assertの有効
[Assertion]
zend.assertions = 1
# 言語の設定を日本語化
[mbstring]
mbstring.language = Japanese
default.conf
次は、nginxのdefault.confを記載していきます。こちらにはサーバの設定やAppサーバーへ接続するための設定を書き込める見たいです。
このファイルでnginxのFastCGIでの設定を色々することでWebサーバーとアプリケーションが繋がるようになります。(Fast CGIとはホームページでプログラムを動かすための仕組みで、ここの設定でphp-fpmと連携してくれるようです。)
server {
# サーバが使用するポートを指定
listen 80;
root /var/www/web-site/public;
index index.php;
location / {
index index.php;
# $uri $uri/ を探し,見つからなければ/index.php$query_stringへ転送。
# $query_stringは/index.php?[名前=値]の?[名前=値]を取得してくれる
try_files $uri $uri/ /index.php$query_string;
}
location ~ \.php$ {
# エラーページ404の表示
try_files $uri =404;
# PATH_INFO 部の分割に使用する正規表現を指定
# 一つ目 ( .+\.php ) は $fastcgi_script_name の値になり、二つ目 ( /.+ ) は $fastcgi_path_info の値になる
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# nginxからphpに受け渡すポートの設定
fastcgi_pass php:9000;
fastcgi_index index.php;
# 設定ファイルを読み込む
include fastcgi_params;
# FastCGIに渡るパラメータを設定
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
これで一旦起動の準備が整いました。色々な記載がありましたが、改めて人に伝えようとすると見てなかったところまで見えるようで少し楽しくなってきますよね。では、早速準備したdocker composeを使ってコンテナを起動させてみたいと思います!
起動するには次のコマンドを打ち込みます。
docker compose up -d
こちらのコマンドを実行すると、ちょっとグルグルと読み込みは発生した後にちゃんと起動できると以下のような表示がされます。実行結果を見ると各コンテナがStarted
の表示になっており、無事に起動できたことがわかります。
web-site % docker compose up -d
[+] Building 0.0s (0/0) docker:desktop-linux
[+] Running 3/3
✔ Container web_db Started 1.2s
✔ Container web_nginx Started 0.2s
✔ Container php Started 0.2s
これでコンテナの起動が確認でしました!
あとはちゃんとLaravelのウェルカムページが見えるか確認してみたいと思います。
docker-compose.ymlで設定した、nginxで決めたポートにアクセスしてみましょう。
今回は8000番を開けてるので、http://localhost:8000 になります。
無事に表示されたようで、ホッとしました。一旦はこれで環境構築の終了です!
(実のところ表示までに紆余曲折あったのですが・・・。そちらに関しては近いうちにLaravelについて記事を書きたいと思います。DBとの疎通確認などもありますしね。)
ということで、今回のまとめに入りたいと思います。
今回はdocker composeを使ってPHP+nginx+Mysqlの組み合わせでphpアプリケーションが動く開発環境を作成しました。
初めてdockerを触り、環境構築をしましたが用意したものがちゃんと動くの楽しいですね。今回は0から構築が終わるまでかなりの時間を要してしまいましたが一度作れば後は何度でも使いまわせるのは便利。まだまだdocker composeの中身もコピペや見様見真似で動かしていますが、一つ一つを理解してdockerを使っていきたいなーと考えています。
もちろん、環境構築だけでなくLaravelなどフレームワークのこともどんどん知りたいので、学んだことをまとめたら記事にしたいですね。
では、2024年も寒さに負けず頑張っていきたいと思います。ぜひ次回もお付き合いください!