27
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ミライトデザインAdvent Calendar 2021

Day 22

docker-laravel の Docker 構成をちゃんと理解する【Dockerfile 編 - PHP】

Last updated at Posted at 2021-12-22

昨日はブッチさんのミライトデザインに入ってからの1年を振り返る記事でした。

ブッチさんとはお互いがミライトデザインに入る前から知り合いだったので、今同じ会社で仕事をしているのが不思議な感じですね。

この記事について

@ucan-lab さんの docker-laravel をちゃんと理解したいので調べるという目的の記事です。

前回の記事では飛ばしていた Dockerfile について調べていきます。

docker-compose.yml の他の記述に関しては前回の記事で解説しています。

Dockerfile のコマンド

各 Dockerfile の詳細を見る前に docker-laravel で使われている Dockerfile のコマンドを確認します。

  • FROM

  • ビルドステージを初期化して、ベース・イメージを指定

    • ビルドステージを初期化っていうのはおそらく、以前のビルド結果に影響を受けづに、新規でビルドを開始するみたいなイメージのはず
  • ベース・イメージは以降の命令から影響を受ける

    • ベースイメージに対してファイルをコピーしたりとか
  • LABEL

  • イメージにメタデータを追加する。

  • key と value の組み合わせ

  • コンテナの動作に影響はない

  • SHELL

  • shell で使われるデフォルトのコマンドを上書きできる

  • ENV

  • ビルドステージ内での環境変数を指定する

  • COPY

  • COPY <コピー元:ホストマシン> <コピー先:Docker内>

  • ホスト(自分の Mac とか) から Docker のコンテナ内にファイルやディレクトリをコピーできる

  • RUN

  • シェルでコマンドを実行できる

  • ホストではなくコンテナ内で実行される

  • WORKDIR

  • RUNCMDENTRYPOINTCOPYADD 命令の処理時に(コマンドを実行する場所として)使う 作業ディレクトリworking directory を指定します。

  • ディレクトリが存在しなければ作成する

php

Dockerfile
# ① ベースイメージを指定
FROM php:8.0-fpm-bullseye  
# ② メタデータを追加
LABEL maintainer="ucan-lab <yes@u-can.pro>" 
# ③ デフォルトのシェルをオーバーライド
SHELL ["/bin/bash", "-oeux", "pipefail", "-c"] 

# --- ④ 環境変数を設定 ---
# timezone environment
ENV TZ=UTC \
  # locale
  LANG=en_US.UTF-8 \
  LANGUAGE=en_US:en \
  LC_ALL=en_US.UTF-8 \
  # composer environment
  COMPOSER_ALLOW_SUPERUSER=1 \
  COMPOSER_HOME=/composer
# ------

# ⑤ composer をインストール
COPY --from=composer:2.1 /usr/bin/composer /usr/bin/composer 
# --- ⑥ イメージ上に任意のコマンドを実行 ---
RUN apt-get update && \
  apt-get -y install git libicu-dev libonig-dev libzip-dev unzip locales && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/* && \
  locale-gen en_US.UTF-8 && \
  localedef -f UTF-8 -i en_US en_US.UTF-8 && \
  mkdir /var/run/php-fpm && \
  docker-php-ext-install intl pdo_mysql zip bcmath && \
  composer config -g process-timeout 3600 && \
  composer config -g repos.packagist composer https://packagist.org
# ------

# ⑦ zzz-www.conf をコンテナにコピー
COPY ./infra/docker/php/php-fpm.d/zzz-www.conf /usr/local/etc/php-fpm.d/zzz-www.conf
# ⑧ php.ini をコンテナにコピー
COPY ./infra/docker/php/php.ini /usr/local/etc/php/php.ini

# ⑨ 作業ディレクトリを指定
WORKDIR /work/backend

① ベースイメージを指定

FROM php:8.0-fpm-bullseye

  • php のイメージを Dockerhub から取得している

  • 本家に詳しい解説が乗っていました。

PHPのイメージタグの種類として cli, apache, fpm, zts の4種類が用意されています。

  • ここで apache なんかを選択すると nginx のコンテナを立てて、unix ソケットで通信して、みたいなことは必要なくる。

    • nginx のコンテナが必要なくなって、php と mysql だけで良くなる(phpのコンテナに apache がすでに入っていることになるので)
  • os は bullseye を使用している

    • bullseys は Debian のバージョン11

② メタデータを追加

LABEL maintainer="ucan-lab <yes@u-can.pro>"

  • ucan さんがメンテナンスしてるよって書いてあるだけ、動作に影響はない

③ デフォルトのシェルをオーバーライド

本家

  • Linux のデフォルトのシェル(["/bin/sh", "-c"])から bash に変更している
  • pipefail あたりのオプションでエラーを見やすくしたりしてる

あんまりわかってないけど、シェルの設定っぽいので今回はいいかな ...

④ 環境変数を設定

本家

TZ=UTC

  • OS(Debian) のタイムゾーンを UTC に設定している

LANG=en_US.UTF-8, LANGUAGE, LC_ALL

  • 言語設定をしている
  • 優先順とか色々あるらしい

⑤ composer をインストール

COPY --from=composer:2.1 /usr/bin/composer /usr/bin/composer

本家

--from オプションを付けると別のイメージのファイルを指定できます。(マルチステージビルド)
composer のインストールがとてもシンプルになっています。

  • dockerhub の composer:2.1 のイメージから composer をベースイメージにコピーしている

⑥ イメージ上に任意のコマンドを実行

RUN apt-get update && \
  apt-get -y install git libicu-dev libonig-dev libzip-dev unzip locales && \
  apt-get clean && \
  rm -rf /var/lib/apt/lists/* && \
  locale-gen en_US.UTF-8 && \
  localedef -f UTF-8 -i en_US en_US.UTF-8 && \
  mkdir /var/run/php-fpm && \
  docker-php-ext-install intl pdo_mysql zip bcmath && \
  composer config -g process-timeout 3600 && \
  composer config -g repos.packagist composer https://packagist.org

本家

ワンライナーで実行することによって、イメージレイヤ数を減らすことができます。

  • \ で繋いでいつのはイメージのレイヤ数を減らすため

  • コンテナに対する変更の差分がレイヤ
  • レイヤが増えると Docker image が大きくなってしまうため、できる限り減らしている

apt-get update

update

  • パッケージを管理している DB を最新にする
  • ライブラリ自体の更新は行わない

apt-getコマンドは、Debian系のディストリビューション(DebianやUbuntu)のパッケージ管理システムであるAPT(Advanced Package Tool)ライブラリを利用してパッケージを操作・管理するコマンドです。

  • FROM で指定したベースイメージが bullseye(Debian のバージョン 11) を使っているので apt-get が使える

apt-get -y install git libicu-dev libonig-dev libzip-dev unzip locales

install

  • 指定されたライブラリをインストール

  • -y 問い合わせが来たら全て yes と答える

  • git

    • お馴染みの git
  • libicu-dev

    • Unicode 用の国際化コンポーネントの開発用ファイル
    • なんでいるんだろ?言語設定とかで必要なんかな?
  • libonig-dev

    • 正規表現のライブラリっぽい
  • libzip-dev

    • zip の作成読み取りなど
  • unzip

    • zip ファイル展開のためのライブラリ
  • locales

    • ローカルの他言語サポートのためのライブラリ

(どのタイミングで使われるのかあんまりわかってないな。無いと Laravel 動かないのか?)

apt-get clean

パッケージをインストールするために拾ってきたアーカイブファイル( *.tar.gz とか)を削除

rm -rf /var/lib/apt/lists/*

ubuntu の記事だけど、UbuntuDebian をベースに派生したらしいから、おそらく似たようなもん)
https://eng-entrance.com/linux-debian-ubuntu

  • /etc/apt/sources.listapt-get で更新したファイル)に基づいて、パッケージインデックスファイル がダウンロードされる

  • インデックスファイル/var/lib/apt/listsに保存される

    • インデックスファイルはパッケージの情報で、インデックスファイルからインストールされているソフトウェアのバージョンを比較して、
      新しいバージョンが存在するかなどを確認しているらしい
  • ここでは、rm -rf/var/lib/apt/lists を削除してる

    • /var/lib/apt/lists を削除して、イメージのサイズを減らすのがベストプラクティスらしい
    • もう使わないから消しても問題ないってことなんだろうな

locale-gen en_US.UTF-8

DockerでbuildしたイメージはロケールがPOSIXになっている。これに起因して、文字コード変換まわりの不具合が発生したりする。

そしてこれがDockerfileに書く設定

RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8




- `④ 環境変数を設定` はこのためにやってるっぽい
- `locale-gen` コマンドが何をやってるのかがよくわからない

https://qiita.com/aosho235/items/58e2e7acd5c2ee3641ff#%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AB%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E3%81%8C%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E5%A0%B4%E5%90%88


>locale-genはシェルスクリプトになっていて、内部で

>```
localedef -i ja_JP -c -f UTF-8 -A /usr/share/locale/locale.alias ja_JP.UTF-8

に相当することをやっている。

  • ちょっとよくわからないけど、一旦ここまで

mkdir /var/run/php-fpm

  • /var/run/php-fpm ディレクトリを作成している
  • docker-compose.yml で UNIX ソケットでマウントしてたディレクトリ
  • デフォルトでは作成されないのかな?
docker-compose.yml
volumes:
      - type: volume
        source: php-fpm-socket
        target: /var/run/php-fpm
        volume:
          nocopy: true

docker-php-ext-install intl pdo_mysql zip bcmath

  • Laravel の動作に必要な PHP の拡張機能があるらしい

  • このコマンドで全てインストールしてるわけじゃなさそう
docker-php-ext-install
  • 公式が用意してくれている PHP の拡張ライブラリをインストールするためのコマンド
    • インストールしたライブラリの有効化までやってくれているっぽい
intl
  • 国際化関数

ケール関連のさまざまな操作を行えるようにします。 フォーマット、音訳、エンコード変換、カレンダーの処理、 » UCA 準拠の照合順序 (collation)、 テキストの区切り、ロケール識別子やタイムゾーンや書記素を用いた操作などが可能です。

pdo_mysql

PDO_MYSQL は、PHP から MySQL データベースへのアクセスを可能にするための PHP Data Objects (PDO) インターフェイス を実装したドライバです。

zip

この拡張モジュールにより、ZIP 圧縮されたアーカイブとその内部のファイルに対する透過的な読み書きが可能となります。

bcmath

任意の精度の演算をサポートするために、PHP は 2147483647 (または 0x7FFFFFFF) までの 任意のサイズおよび精度の小数桁をサポートする BCMath を提供します。 十分なメモリがあれば、文字列表現もサポートします。

有効(別名 well-formed) な BCMath数 は、以下の正規表現にマッチする文字列です。 /^[+-]?[0-9](.[0-9])?$/.

composer config -g process-timeout 3600

composer のプロセスがタイムアウトしないように上限時間を伸ばしている

config コマンドは、ローカルの composer.json ファイルまたはグローバルな config.json ファイルにある Composer の設定とリポジトリを編集することができます。

デフォルトでは $COMPOSER_HOME/config.json にあるグローバルな設定ファイルに対して操作します。このオプションがない場合は、ローカルの composer.json ファイルか、-file で指定したファイルに作用します。

プロセス実行の秒単位のタイムアウト。デフォルトは300(5分)です。 git clonesのような期間プロセスは、Composerがそれらが消滅したと想定する前に実行できます。接続が遅い場合やベンダーが巨大な場合は、これを高くする必要があります。

composer config -g repos.packagist composer https://packagist.org

PHPのライブラリリポジトリであるhttps://packagist.orgのミラーサイトです。packagist.orgの代わりにこちらを参照することで、composer updateの応答速度が速くなります。特にフランスから遠い、アジア圏では顕著な効果が得られます。

有効にするには以下のコマンドを打ち込んでください。

enable
$ composer config -g repos.packagist composer https://packagist.jp

zzz-www.conf をコンテナにコピー

COPY ./infra/docker/php/php-fpm.d/zzz-www.conf /usr/local/etc/php-fpm.d/zzz-www.conf

  • php-fpm の設定項目をマウント している
    • 設定ファイルが zzz-www.conf になってるのは公式イメージにある設定を上書きするためらしい

php.ini をコンテナにコピー

  • php.ini
    • php の設定をするファイル

⑨ 作業ディレクトリを指定

WORKDIR 命令は、Dockerfile 内で以降に続く RUN 、 CMD 、 ENTRYPOINT 、 COPY 、 ADD 命令の処理時に(コマンドを実行する場所として)使う 作業ディレクトリworking directory を指定します。 WORKDIR が存在していなければ作成されます。これは、以降の Dockerfile で使われなくてもです。

  • ここでは WORKDIR がなければ作成されるだけ

php-fpm.d/zzz-www.conf について

zzz-www.conf
[www] ; ① プール名
listen = /var/run/php-fpm/php-fpm.sock ; ② FastCGI のリクエストを受け入れるアドレス
; --- ③ パーミッションの設定 ---
listen.owner = www-data 
listen.group = www-data
listen.mode = 0666
; ------
access.log = /dev/stdout

① プール名

[www]

www って名前をプロセスプールにつけている

② FastCGI のリクエストを受け入れるアドレス

listen = /var/run/php-fpm/php-fpm.sock

listen

FastCGI リクエストを受け入れるアドレス。 'ip.add.re.ss:port', 'port', '/path/to/unix/socket' 形式の構文が使えます。 このオプションは、各プール単位で必須となります。

  • PHP-fpm と Nginx を連携させるには、 TCP か UNIX ドメインソケットのどちらかで通信する

  • docker-compose.yml/var/run/php-fpm をマウントさせているのは UNIX ドメインソケットで通信するため

  • ここで、 UNIX ドメインソケットのパスを指定することで、 UNIX ドメインソケットでの通信が行えている

③ パーミッションの設定

listen.owner = www-data

unix ソケットを使う場合に、そのパーミッションを設定します。Linux では、 読み書きアクセス権限を設定しないとウェブサーバーからの接続を受け付けることができません。 多くの BSD 由来のシステムでは、パーミッションにかかわらず接続を受け付けることができます。 デフォルト値: ユーザーとグループは実行しているユーザーと同じ、モードは 0660

  • www-data は Ubuntu (おそらく Debian でも) 上の Web サーバー(Apache、nginxなど)がデフォルトで通常の操作に使用するユーザー

  • listen.mode = 0660 でも動くのかな?

ログ

php.ini について

php.ini は ucan さんの別記事で詳しく解説してありましたのでここでは深堀はしません。

おわり

まだ MySql と Nginx の Dockerfile も残っているので、せっかくなのでアドカレとは別で書きたいと思います。(そのうち)

明日は yuki の GAE についての記事らしいです。
よろしくお願いします!

27
14
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?