Docker 20.10.1
— y2sunlight 2020-12-20
関連記事
リンク
PHPを例にとって、Dockerコンテナの作成方法を説明します。この例では、Docker Hubの公開リポジトリ(パブリックリポジトリ)で配布されているPHPコンテナを使って、自分用に設定したPHPのDockerイメージを作成します。
本章の実行例は WindowsターミナルのUbuntuターミナルで実行しています。dockerの初期設定については、こちらを参照して下さい。
Dockerイメージは、多層構造になっていて、それらの各層(レイア)が透過的に重なり1つのファイルシステムを構成しています。各層はディレクトリやファイルを含み、またはメタ情報だけの層もあります。Docker イメージを作成する場合は、ベースとなる層の上に自分のイメージを作成します。このベースとなるイメージを以降は「ベースイメージ」と呼びます。
多くの場合、Dockerイメージは、その基になるベースイメージから始まります。そのイメージは親イメージと呼ばれ、Docker Hub から取得できます。本章では、以下のベースイメージを使用します。
この中の Apache+PHP7.4 用のコンテナから、タグ 7.4-apache
のイメージをdocker pull コマンドでダウンロードします:
$ docker pull php:7.4-apache
PHPコンテナのベースイメージはパッケージの依存関係などもありOSのベースが本番環境ともに同じものを利用します。ここで選択したphp:7.4-apache
のOSのベースは、このイメージの Dockerfile を調べると debian:buster-slim
だという事が分かります。このベースは Debian 10 で処理系なしの軽量な実行環境用のイメージです。
OSのベースイメージ選びについては、以下のサイトが参考になりました:
ダウンロードしたDockerイメージ php:7.4-apache
を 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
次に、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の設定ファイルの場所と名前が分かったので、それをホスト側にコピーします。この作業は、別のターミナルを起動してホスト側で、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 ./
ホスト側で、先にコンテナから取得した以下のファイルを編集します。
ここでは、例として以下のように 000-default.conf
を修正します。
<VirtualHost *:80> ... # For testing docker <Directory /var/www/html> Options Indexes FollowSymLinks Includes ExecCGI AllowOverride All Require all granted </Directory> ... </VirtualHost>
/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が表示されます。
以下のように、hello.html と info.php を新しく作成します:
作成したファイルをコンテナのドキュメントルートにコピーします:
$ docker cp ./hello.html php74:/var/www/html/ $ docker cp ./info.php php74:/var/www/html/
Winodws側のプラウザから http://localhost:8080/
にアクセスするとコンテナのドキュメントルーツのindexが表示されます。
DockerイメージにPHP拡張モジュールを追加する場合の視点は次の4つがあります:
DockerでのPHP拡張モジュールの追加については、是非、以下のURLの「How to install more PHP extensions」の項を一読されることを推奨します。
以下に「その他の拡張モジュール」を除くそれぞれの場合について説明します。
多くの拡張モジュールは既にコンパイルされてモジュールに格納されています。本章では、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 Dockerイメージ を利用して、インストールできる拡張モジュールを指しています。「公式PHP Dockerイメージ」を親に持つベースイメージを使う場合は、この方法が利用できます。どの拡張モジュールが対象となっているかは、以下の docker-php-extension-installer
プロジェクトの Supported PHP extensions
を参照して下さい:
これらの拡張モジュールは、圧縮されて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
に拡張モジュールの有効性を設定します。
例として PHP拡張モジュール gd
をインストールします。gd は使用する画像イメージの種類によって様々なバリエーションがあります。以下のサイトに詳しい説明があります。ここでは、png と jpeg が使えるようにします。
以下の作業は、コンテナ内で行います。
まずは、パッケージの一覧を更新します:
# 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
がインストールされているのが確認できます。
PECLからインストールするには、[https://www.php.net/manual/ja/install.pecl.pear.php|pecl コマンド]を使用します。pecl install
を使用してダウンロードしてコンパイルしてから、docker-php-ext-enable
を使用して拡張モジュールを有効にします。
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
最後に、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
がインストールされているのが確認できます。
以下の作業はホストで行います。
開始中のコンテナ(php74
)を停止します。
$ docker stop php74
これまでに作成したコンテナをDockerイメージとして保存するには、docker commit コマンドを使います。
$ docker commit php74 myphp74:2020-12-22 sha256:d743369242c56be71e47f1e7ad0f5b218ff8a61c923643fc475c6d01dbb23cda
保存したDockerイメージを 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コンテナを作成しイメージとして保存しました。これら一連のDockerイメージの作成過程を自動化してくれるのが「Dockerfile」です。Dockerfile とは、Docker イメージを作成する時のコマンドを1つのファイルにまとめたもので、Docker コンテナの構成情報を記述するためのファイルです。
これまでの項で作成してものと全く同じDockerイメージを本項では Dockerfile を使って作成します。以下の作業は全てホストで行います。
ホームディレクトリ下に以下の作業ディレクトリを作成します:
~/docker/php7.4
このディレクトリの中にこれまでに作成した次のファイルを準備します。
以下のように、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 の詳細については、以下を参照して下さい:
Dockerfileの準備が出来たら、docker build コマンドを使って新しい Docker イメージを構築します。
$ docker build -t myphp74:2020-12-23 .
-t
— '名前:タグ' 形式でイメージの名前とタグ(オプション)を指定します。.
)はソースコードのパス(ここではカレントディレクトリ)を指定します。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 ...
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 <missing> 11 days ago /bin/sh -c #(nop) EXPOSE 80 0B <missing> 11 days ago /bin/sh -c #(nop) WORKDIR /var/www/html 0B ... <missing> 12 days ago /bin/sh -c #(nop) ADD file:3a7bff4e139bcacc5… 69.2MB
Dockerfileに記述した降順にレイヤー作成されているのが分かります。CMD [“apache2-foreground”]
以下のレイヤーはベースイメージのものです。
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 に関して本章で説明するのは情報過多なので、改めて以下の章で説明することにします: