$ docker pull php:7.4-apache
PHPコンテナのベースイメージはパッケージの依存関係などもありOSのベースが本番環境ともに同じものを利用します。ここで選択した''php:7.4-apache'' のOSのベースは、このイメージの [[https://github.com/docker-library/php/blob/0274f58b8dcf68a23d8fd77101d2d4c74d38fc65/7.4/buster/apache/Dockerfile|Dockerfile]] を調べると ''debian:buster-slim'' だという事が分かります。このベースは Debian 10 で処理系なしの軽量な実行環境用のイメージです。
OSのベースイメージ選びについては、以下のサイトが参考になりました:
* https://blog.mosuke.tech/entry/2020/07/09/container-image-size/
\\
===== ベースイメージの調査 =====
ダウンロードしたDockerイメージ ''php:7.4-apache'' を [[http://docs.docker.jp/v17.06/engine/reference/commandline/run.html|docker run]] コマンドでコンテナとして開始します。この時、操作し易いようにコンテナに名前( ''php74'' )を付け、またホストからブラウザでアクセスできるようにポート ''8080'' にフォワードしています:
$ docker run --name php74 -d -p 8080:80 php:7.4-apache
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
373a10d11ec1 php:7.4-apache "docker-php-entrypoi…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp php74
次に、[[http://docs.docker.jp/v17.06/engine/reference/commandline/run.html|docker exec]] コマンドで ''php74'' コンテナ内で、''bash'' コマンドを実行します:
$ docker exec -it php74 bash
これで、ベースイメージを調査する準備ができました。
Apacheの設定ファイル( ''apache2.conf'' )の場所を確認します:
# ls -l /etc/apache2/apache2.conf
-rw-r--r-- 1 root root 7224 Aug 25 20:08 /etc/apache2/apache2.conf
Apacheのサイト構成ファイル( ''000-default.conf'' )の場所を確認します:
# ls -l /etc/apache2/sites-available/000-default.conf
-rw-r--r-- 1 1000 1000 1469 Dec 21 06:06 /etc/apache2/sites-available/000-default.conf
以下のようにして、PHPの設定ファイルの場所を調べます。
# php -r "phpinfo();" | grep php.ini
Configuration File (php.ini) Path => /usr/local/etc/php
# ls /usr/local/etc/php -l
total 148
drwxr-xr-x 1 root root 4096 Dec 11 08:24 conf.d
-rw-r--r-- 1 root root 72553 Dec 11 08:24 php.ini-development
-rw-r--r-- 1 root root 72583 Dec 11 08:24 php.ini-production
これで、ApacheとPHPの設定ファイルの場所と名前が分かったので、それをホスト側にコピーします。この作業は、別のターミナルを起動してホスト側で、[[http://docs.docker.jp/v17.06/engine/reference/commandline/run.html|docker cp]] コマンドを使って行います:
$ docker cp php74:/etc/apache2/apache2.conf .
$ docker cp php74:/etc/apache2/sites-available/000-default.conf .
$ docker cp php74:/usr/local/etc/php/php.ini-development ./
$ docker cp php74:/usr/local/etc/php/php.ini-production ./
\\
===== コンテナ内のファイルの変更と追加 =====
==== 設定ファイルの変更 ====
ホスト側で、先にコンテナから取得した以下のファイルを編集します。
* apache2.conf --- Apacheの設定ファイル
* 000-default.conf --- Apacheのサイト構成ファイル
* php.ini-development --- PHPの設定ファイル
ここでは、例として以下のように ''000-default.conf'' を修正します。
...
# For testing docker
Options Indexes FollowSymLinks Includes ExecCGI
AllowOverride All
Require all granted
...
* ドキュメントルート ''/var/www/html'' のファイル一覧表示を許可
* その他、ほとんどの操作を許可しています
編集が終わったら、これらの設定ファイルをコンテナにコピーします。
$ docker cp ./apache2.conf php74:/etc/apache2/
$ docker cp ./000-default.conf php74:/etc/apache2/sites-available/
$ docker cp ./php.ini-development php74:/usr/local/etc/php/php.ini
コンテナを再起動します:
$ docker restart php74
Winodws側のプラウザから ''http://localhost:8080/'' にアクセスするとコンテナのドキュメントルーツのindexが表示されます。
[{{:docker:20:build:docker-20-build01.png?nolink}}]
\\
==== htmlとphpファイルの設置 ====
以下のように、hello.html と info.php を新しく作成します:
Hello form Docker!
作成したファイルをコンテナのドキュメントルートにコピーします:
$ docker cp ./hello.html php74:/var/www/html/
$ docker cp ./info.php php74:/var/www/html/
Winodws側のプラウザから ''http://localhost:8080/'' にアクセスするとコンテナのドキュメントルーツのindexが表示されます。
[{{:docker:20:build:docker-20-build02.png?nolink}}]
\\
===== PHP拡張モジュールの追加 =====
DockerイメージにPHP拡張モジュールを追加する場合の視点は次の4つがあります:
- コンパイル済の拡張モジュール --- ベースイメージのPHPに既にコンパイルされて追加されている
- PHPコア拡張モジュール --- [[https://hub.docker.com/_/php/|公式PHP Dockerイメージ]]を利用して簡単にインストールできる
- PECL拡張モジュール --- PECLから入手できる(peclコマンドを使います)
- その他の拡張モジュール --- phpize、make コマンドなどを使って手動でインストールする
DockerでのPHP拡張モジュールの追加については、是非、以下のURLの「How to install more PHP extensions」の項を一読されることを推奨します。
* https://hub.docker.com/_/php
以下に「その他の拡張モジュール」を除くそれぞれの場合について説明します。
\\
==== コンパイル済の拡張モジュール ====
多くの拡張モジュールは既にコンパイルされてモジュールに格納されています。本章では、apache ドキュメントルートに作成した ''info.php'' からそれを調べることができます:
http://localhost:8080/info.php
また、コンテナ内部から ''php -m'' コマンドでこれを確認することもできます。実行例:
# php -m
[PHP Modules]
Core
ctype
curl
date
dom
fileinfo
filter
ftp
hash
iconv
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_sqlite
Phar
posix
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib
これらのモジュールについては既に存在するので追加の必要はありません。
\\
==== PHPコア拡張モジュールの追加 ====
ここで言う「 PHPコア拡張モジュール」とは[[https://hub.docker.com/_/php/|公式PHP Dockerイメージ]] を利用して、インストールできる拡張モジュールを指しています。「公式PHP Dockerイメージ」を親に持つベースイメージを使う場合は、この方法が利用できます。どの拡張モジュールが対象となっているかは、以下の ''docker-php-extension-installer'' プロジェクトの ''Supported PHP extensions'' を参照して下さい:
* https://github.com/mlocati/docker-php-extension-installer
これらの拡張モジュールは、圧縮されてDockerイメージの中に含まれており、以下の3つのヘルパースクリプトを使って簡単にインストールできます。
* ''docker-php-ext-configure'' --- 拡張モジュールにカスタム構成が必要な場合に ''docker-php-ext-install'' の前に実行します。
* ''docker-php-ext-install'' --- 拡張モジュールをインストールします。
* ''docker-php-ext-enable'' --- ''pecl'' コマンドなど、''docker-php-ext-instal'' 以外で拡張モジュールをインストールした後に使用し、''php.ini'' に拡張モジュールの有効性を設定します。
=== 例:gdのインストール ===
例として PHP拡張モジュール ''gd'' をインストールします。gd は使用する画像イメージの種類によって様々なバリエーションがあります。以下のサイトに詳しい説明があります。ここでは、png と jpeg が使えるようにします。
* https://tt-computing.com/docker-php-gd
以下の作業は、コンテナ内で行います。
まずは、パッケージの一覧を更新します:
# apt update
gd の使用するパッケージをインストールします:
# apt install -y zlib1g-dev libpng-dev libjpeg62-turbo-dev
gd をインストールし、PHP拡張モジュールとして有効にします:
# docker-php-ext-configure gd --with-jpeg
# docker-php-ext-install -j$(nproc) gd
* ''docker-php-ext-configure'' は ''docker-php-ext-install'' の前で実行する必要があります。
* ''docker-php-ext-install'' の ''-j$(nproc)'' オプションは同時実行できる処理数で、CPU数を指定しています。
* ''docker-php-ext-enable'' は ''docker-php-ext-install'' によって実行されます。
インストール後、''extension_dir'' の中に ''gd.so'' がインストールされています:
# ls /usr/local/lib/php/extensions/no-debug-non-zts-20190902/*.so -l
-rwxr-xr-x 1 root root 426544 Dec 21 08:41 /usr/local/lib/php/extensions/no-debug-non-zts-20190902/gd.so
...
また、php.iniのインクルードファイルが追加されています:
# ls -l /usr/local/etc/php/conf.d/*.ini
-rw-r--r-- 1 root root 16 Dec 21 08:41 /usr/local/etc/php/conf.d/docker-php-ext-gd.ini
...
extension=gd.so
''exit'' でコンテナから出て、ホストでコンテナ(''php74'')を再起動します。
$ docker restart php74
Winodws側のプラウザから ''http://localhost:8080/info.php'' にアクセスすると ''gd'' がインストールされているのが確認できます。
[{{:docker:20:build:docker-20-build03.png?nolink}}]
\\
==== PECL拡張モジュールの追加 ====
[[https://pecl.php.net/|PECL]]からインストールするには、[https://www.php.net/manual/ja/install.pecl.pear.php|pecl コマンド]を使用します。''pecl install'' を使用してダウンロードしてコンパイルしてから、''docker-php-ext-enable'' を使用して拡張モジュールを有効にします。
=== 例:memcachedのインストール ===
PECL からインストール例として memcached を取り上げます。以下の作業は、コンテナ内で行います。
まず、パッケージの一覧を更新し、memcached が依存しているパッケージをインストールしておきます:
# apt update
# apt install -y libmemcached-dev
pecl コマンドを使用して、memcached インストールします:
# pecl install memcached
以下は、インストールの実行例です:
# pecl install memcached
pecl/memcached can optionally use PHP extension "igbinary" (version >= 2.0)
pecl/memcached can optionally use PHP extension "msgpack" (version >= 2.0)
...
libmemcached directory [no] : # [Enter]入力
zlib directory [no] : # [Enter]入力
use system fastlz [no] : # [Enter]入力
enable igbinary serializer [no] : # [Enter]入力
enable msgpack serializer [no] : # [Enter]入力
enable json serializer [no] : # [Enter]入力
enable server protocol [no] : # [Enter]入力
enable sasl [yes] : # [Enter]入力
enable sessions [yes] : # [Enter]入力
...
Build process completed successfully
Installing '/usr/local/lib/php/extensions/no-debug-non-zts-20190902/memcached.so'
install ok: channel://pecl.php.net/memcached-3.1.5
configuration option "php_ini" is not set to php.ini location
You should add "extension=memcached.so" to php.ini
* インストールの最中にオプションを聞かれますが、全て[Enter]を入力します。
最後に、''docker-php-ext-enable'' を使用して拡張モジュールを有効にします:
# docker-php-ext-enable memcached
インストール後、extension_dir の中に gd.so がインストールされています:
# ls /usr/local/lib/php/extensions/no-debug-non-zts-20190902/*.so -l
-rw-r--r-- 1 root root 729464 Dec 22 13:29 /usr/local/lib/php/extensions/no-debug-non-zts-20190902/memcached.so
...
また、php.iniのインクルードファイルが追加されています:
# ls -l /usr/local/etc/php/conf.d/*.ini
-rw-r--r-- 1 root root 20 Dec 21 11:32 docker-php-ext-memcached.ini
...
extension=memcached
exit でコンテナから出て、ホストでコンテナ(php74)を再起動します:
$ docker restart php74
Winodws側のプラウザから ''http://localhost:8080/info.php'' にアクセスすると ''memcached'' がインストールされているのが確認できます。
[{{:docker:20:build:docker-20-build04.png?nolink}}]
\\
===== イメージの保存 =====
以下の作業はホストで行います。
開始中のコンテナ(''php74'')を停止します。
$ docker stop php74
これまでに作成したコンテナをDockerイメージとして保存するには、[[http://docs.docker.jp/v17.06/engine/reference/commandline/commit.html|docker commit]] コマンドを使います。
$ docker commit php74 myphp74:2020-12-22
sha256:d743369242c56be71e47f1e7ad0f5b218ff8a61c923643fc475c6d01dbb23cda
保存したDockerイメージを
[[http://docs.docker.jp/v17.06/engine/reference/commandline/images.html|docker images]] コマンドで確認します。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myphp74 2020-12-22 62df1ffadc6f About a minute ago 439MB
...
保存したDockerイメージを起動します。
$ docker run --name myphp74 -d -p 8080:80 myphp74:2020-12-22
23d84d5ce0837cdbf171695c417fe387793aadbdf497b341d24d398ef9ae809a
Winodws側のプラウザから ''http://localhost:8080/info.php'' にアクセスして、''gd'' と ''memcached'' がインストールされているか確認して下さい。
[{{:docker:20:build:docker-20-build05.png?nolink}}]
\\
===== Dockerfile =====
これまでの項では、手動でDockerコンテナを作成しイメージとして保存しました。これら一連のDockerイメージの作成過程を自動化してくれるのが「Dockerfile」です。Dockerfile とは、Docker イメージを作成する時のコマンドを1つのファイルにまとめたもので、Docker コンテナの構成情報を記述するためのファイルです。
これまでの項で作成してものと全く同じDockerイメージを本項では Dockerfile を使って作成します。以下の作業は全てホストで行います。
\\
==== 作業ディレクトリの準備 ====
ホームディレクトリ下に以下の作業ディレクトリを作成します:
~/docker/php7.4
このディレクトリの中にこれまでに作成した次のファイルを準備します。
* Dockerfile --- コンテナ構成ファイル
* apache2.conf --- Apacheの設定ファイル
* 000-default.conf --- Apacheのサイト構成ファイル
* php.ini-development --- PHPの設定ファイル(開発用)
* php.ini-production --- PHPの設定ファイル(本番用)
* hello.html --- テスト用のhtml ファイル
* info.php --- テスト用のphpファイル
\\
==== Dockerfile ====
以下のように、Dockerfile を編集します:
FROM php:7.4-apache
#
# Apache/PHP Base Settings
#
COPY ./apache2.conf /etc/apache2/
COPY ./000-default.conf /etc/apache2/sites-available/
COPY ./php.ini-development /usr/local/etc/php/php.ini
#
# /var/www/html/
#
COPY ./hello.html /var/www/html/
COPY ./info.php /var/www/html/
#
# Install PHP Extensions
#
# gd
#
RUN apt-get update
RUN apt-get install -y zlib1g-dev libpng-dev libjpeg62-turbo-dev \
&& docker-php-ext-configure gd --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd
#
# memcached
#
RUN apt-get install -y libmemcached-dev \
&& pecl install memcached \
&& docker-php-ext-enable memcached
* ''FROM'' --- イメージ構築の初期化を実行し、ベースイメージを設定します。Dockerfileは必ず''FROM''命令から始まります。
* ''COPY'' --- ホスト内のファイルやディレクトリをコンテナ内のファイルシステムに追加します。
* ''RUN'' --- 現在の最新イメージにおいて、コンテナ内でコマンドを実行します。コマンドが成功するとイメージは確定され、Dockerfile の次のステップで利用されます。
> Dockerfileで ''apt'' を使うと次の警告が出るので ''apt-get'' を使いました。
>>WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
> また、''apt-get'' を使うと今度は次の警告がでます。buildの動作的にはは問題なさそうですが調査中です。
>>debconf: delaying package configuration, since apt-utils is not installed
Dockerfile の詳細については、以下を参照して下さい:
* [[https://docs.docker.jp/engine/reference/builder.html|Dockerfile リファレンス]] --- Docker日本語ドキュメント
\\
==== Dockerイメージの作成 ====
Dockerfileの準備が出来たら、[[https://docs.docker.jp/engine/reference/commandline/build.html|docker build]] コマンドを使って新しい Docker イメージを構築します。
$ docker build -t myphp74:2020-12-23 .
* ''-t'' --- '名前:タグ' 形式でイメージの名前とタグ(オプション)を指定します。
* コマンドの最後の引数( ''.'' )はソースコードのパス(ここではカレントディレクトリ)を指定します。
[[https://docs.docker.jp/engine/reference/commandline/images.html|docker images]] コマンドでDockerイメージの一覧を表示します:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
REPOSITORY TAG IMAGE ID CREATED SIZE
myphp74 2020-12-23 d849c91871fd 15 minutes ago 440MB
myphp74 2020-12-22 62df1ffadc6f 13 hours ago 439MB
...
[[https://docs.docker.jp/engine/reference/commandline/history.html|docker history]] コマンドでイメージ内のレイヤーを表示します:
$ docker history myphp74:2020-12-23
IMAGE CREATED CREATED BY SIZE COMMENT
d849c91871fd 17 minutes ago /bin/sh -c apt-get install -y libmemcached-d… 4.19MB
30fc1a25dfb9 18 minutes ago /bin/sh -c apt-get install -y zlib1g-dev lib… 4.23MB
17d39386f699 18 minutes ago /bin/sh -c apt-get update 17.5MB
778c23eca0cd 24 minutes ago /bin/sh -c #(nop) COPY file:c9b0bd401ba1924c… 17B
5645b898b5af 24 minutes ago /bin/sh -c #(nop) COPY file:398875164d45e85a… 58B
9fc74c528658 24 minutes ago /bin/sh -c #(nop) COPY file:f9dcd09c7428c2df… 72.6kB
e0878c88c727 24 minutes ago /bin/sh -c #(nop) COPY file:0c73f4a9191f660f… 1.54kB
89628e4477f9 24 minutes ago /bin/sh -c #(nop) COPY file:7a59a6bc15702a48… 7.22kB
fd505f1f4cd8 11 days ago /bin/sh -c #(nop) CMD ["apache2-foreground"] 0B
11 days ago /bin/sh -c #(nop) EXPOSE 80 0B
11 days ago /bin/sh -c #(nop) WORKDIR /var/www/html 0B
...
12 days ago /bin/sh -c #(nop) ADD file:3a7bff4e139bcacc5… 69.2MB
Dockerfileに記述した降順にレイヤー作成されているのが分かります。''CMD ["apache2-foreground"]'' 以下のレイヤーはベースイメージのものです。
\\
==== Dockerイメージの起動 ====
Dockerfileから構築したDockerイメージを起動し、Winodws側のプラウザから ''http://localhost:8080'' にアクセスして確認して下さい。
$ docker run --name myphp74a -d -p 8080:80 myphp74:2020-12-23
7980e3ed36186de445238eae2193b3f505fed04ac03a50c5ac3adb6cc7a405dd
このように Dockerfile を使えば、Dockerイメージを素早く作れるだけでなく、GitHubなどのリポジトリによってチーム内で共有することもできます。
\\
===== イメージのアップロード =====
ここまでで、新しいDockerイメージの作成に関する説明は終わりました。後は、DockerイメージをDocker Hubにアップロードするだけとなりましたが、Docker Hub に関して本章で説明するのは情報過多なので、改めて以下の章で説明することにします:
* [[docker:20:hub|DockerHubの利用(Ship)]]
\\