「VM」の版間の差分
(MySQL default) |
(Configuration) |
||
| (同じ利用者による、間の19版が非表示) | |||
| 100行目: | 100行目: | ||
COPY --from=composer /usr/bin/composer /usr/bin/composer | COPY --from=composer /usr/bin/composer /usr/bin/composer | ||
ヘッダーのあるlib*-devもセットでインストールしておく。 | ヘッダーのあるlib*-devもセットでインストールしておく。 | ||
===== Configuration ===== | |||
dockerのPHP公式イメージにはデフォルトのphp.iniとして、php.ini-development php.ini-productionの2種類が同梱されている。他に、$PHP_INI_DIR/conf.d/も追加されている。デフォルトからカスタマイズしたかったら、conf.dに追加する。 | |||
デフォルトのphp.iniとしてdevelopmentを使うといい。 | |||
RUN ln -fns php.ini-development "$PHP_INI_DIR/php.ini" | |||
===== Composer ===== | ===== Composer ===== | ||
| 107行目: | 113行目: | ||
COPY --from=composer /usr/bin/composer /usr/bin/composer | COPY --from=composer /usr/bin/composer /usr/bin/composer | ||
Dockerの公式イメージのcomposerから該当バイナリーだけをコピーして配置してくれる模様。 | Dockerの公式イメージのcomposerから該当バイナリーだけをコピーして配置してくれる模様。 | ||
===== Oracleイメージ ===== | |||
FROM php:7.4.0-apache | |||
ENV APACHE_DOCUMENT_ROOT /var/www/html | |||
RUN apt-get update && apt-get install -y \ | |||
unzip \ | |||
libaio1 | |||
# custom php.ini | |||
RUN echo "file_uploads = On\n" \ | |||
"memory_limit = -1\n" \ | |||
"upload_max_filesize = 500M\n" \ | |||
"post_max_size = 500M\n" \ | |||
"max_execution_time = 0\n" \ | |||
"output_buffering=4096\n" \ | |||
> /usr/local/etc/php/conf.d/custom.ini | |||
# AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using xx.xx.xx.xx. Set the 'ServerName' directive globally to suppress this message | |||
RUN echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf | |||
RUN a2enconf fqdn | |||
# Install Oracle Instantclient | |||
ADD <nowiki>https://download.oracle.com/otn_software/linux/instantclient/214000/instantclient-basic-linux.x64-21.4.0.0.0dbru.zip</nowiki> /tmp | |||
ADD <nowiki>https://download.oracle.com/otn_software/linux/instantclient/214000/instantclient-sdk-linux.x64-21.4.0.0.0dbru.zip</nowiki> /tmp | |||
RUN unzip /tmp/instantclient-basic-linux.x64-21.4.0.0.0dbru.zip -d /usr/local/ && \ | |||
unzip /tmp/instantclient-sdk-linux.x64-21.4.0.0.0dbru.zip -d /usr/local/ &&\ | |||
ln -s /usr/local/instantclient_21_4 /usr/local/instantclient | |||
ENV NLS_LANG=Japanese_Japan.JA16SJISTILDE | |||
ENV LD_LIBRARY_PATH=/usr/local/instantclient | |||
# Install Oracle extensions | |||
RUN docker-php-ext-configure oci8 --with-oci8=instantclient,/usr/local/instantclient && \ | |||
docker-php-ext-install oci8 && \ | |||
docker-php-ext-configure pdo_oci --with-pdo-oci=instantclient,/usr/local/instantclient,21.4 && \ | |||
docker-php-ext-install pdo_oci && \ | |||
docker-php-ext-enable oci8 | |||
RUN rm -rf /tmp/*.zip | |||
# Composer install | |||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer | |||
# composer updateを実行 | |||
RUN chown www-data:www-data /var/www \ | |||
&& mkdir -p ${APACHE_DOCUMENT_ROOT}/vendor \ | |||
&& mkdir -p ${APACHE_DOCUMENT_ROOT}/var \ | |||
&& chown www-data:www-data ${APACHE_DOCUMENT_ROOT}/vendor \ | |||
&& chmod g+s ${APACHE_DOCUMENT_ROOT}/vendor | |||
USER www-data | |||
COPY composer.json ${APACHE_DOCUMENT_ROOT}/composer.json | |||
#COPY composer.lock ${APACHE_DOCUMENT_ROOT}/composer.lock | |||
RUN composer update \ | |||
--no-scripts \ | |||
--no-autoloader \ | |||
-d ${APACHE_DOCUMENT_ROOT} \ | |||
; | |||
RUN composer dump-autoload | |||
USER root | |||
# Install Crypt_Blowfish | |||
RUN pear install Crypt_Blowfish | |||
# Install Smarty | |||
# ADD <nowiki>https://github.com/smarty-php/smarty/archive/refs/tags/v3.1.39.zip</nowiki> /tmp | |||
# RUN unzip /tmp/v3.1.39.zip -d /usr/local/ &&\ | |||
# ln -s /usr/local/smarty-3.1.39/libs /usr/local/lib/php/Smarty | |||
# RUN rm -rf /tmp/*.zip | |||
# DocumentRootを変更 | |||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}/web2!g' /etc/apache2/sites-available/*.conf | |||
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}/web2!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf | |||
==== phpmyadmin ==== | ==== phpmyadmin ==== | ||
| 148行目: | 228行目: | ||
docker exec -i mysql-container mysql -uuser -ppassword name_db < data.sql | docker exec -i mysql-container mysql -uuser -ppassword name_db < data.sql | ||
上記のようなコマンドで取り込む。 | 上記のようなコマンドで取り込む。 | ||
==== apt update失敗対策 ==== | |||
Dockerfile内でRUN apt update && apt installを実行すると以下のエラーが出る。 | |||
1.327 Err:6 <nowiki>http://deb.debian.org/debian</nowiki> bullseye-updates/main amd64 Packages | |||
1.327 503 Service Unavailable [IP: 10.0.0.28 8080] | |||
1.847 E: Failed to fetch <nowiki>http://deb.debian.org/debian/dists/bullseye-updates/main/binary-amd64/Packages</nowiki> 503 Service Unavailable [IP: 10.0.0.28 8080] | |||
1.847 E: Some index files failed to download. They have been ignored, or old ones used instead. | |||
/main/binary-amd64/Packagesのリポジトリーだけが503でアクセス不能になってエラーになっている。これのせいで、dockerがコマンドが失敗したとみなして、処理を中断している。ただ、このリポジトリーだけがエラーになっているだけで、他のリポジトリーは問題ない。 | |||
apt updateの失敗を無視してapt installを実行すると問題ない。 | |||
RUN apt update && apt install -y unzip | |||
apt installの成否が大事なので。 | |||
==== Server ==== | |||
===== DocumentRootの変更 ===== | |||
[https://hub.docker.com/_/php/ php - Official Image | Docker Hub] | |||
以下のような感じで設定ファイルを書き換える。 | |||
FROM php:7.1-apache | |||
ENV APACHE_DOCUMENT_ROOT=/path/to/new/root | |||
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf | |||
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf | |||
=== Error === | === Error === | ||
| 164行目: | 270行目: | ||
docker compose v2からversion指令は廃止になった。単純に削除すればいい。 | docker compose v2からversion指令は廃止になった。単純に削除すればいい。 | ||
=== | === Command === | ||
[https://docs.docker.jp/engine/reference/commandline/cli.html Docker コマンドラインを使う — Docker-docs-ja 24.0 ドキュメント] | |||
==== $HOME/.docker/config.json ==== | |||
[https://docs.docker.jp/engine/reference/commandline/cli.html Docker コマンドラインを使う — Docker-docs-ja 24.0 ドキュメント] | |||
===== プロキシー設定 ===== | |||
[https://dev.classmethod.jp/articles/how-to-fix-docker-pull-behind-proxy/ プロキシ環境でdocker pullがうまくいかないときに試すこと | DevelopersIO] | |||
{ | |||
"proxies": { | |||
"default": { | |||
"httpProxy": "<プロキシURL>", | |||
"httpsProxy": "<プロキシURL>" | |||
} | |||
} | |||
} | |||
これでDockerfile内でENV http_proxy=などを回避できる。 | |||
==== container ==== | |||
[https://docs.docker.com/reference/cli/docker/container/ docker container | Docker Docs] | |||
===== exec/container run/compose up ===== | |||
よく似た概念のコマンドが複数あって混乱するので整理する。 | |||
* exec: 起動済みのコンテナーイメージ内に入る。 | |||
* container run/compose up: ほぼ同じ。イメージを起動する。container runはコマンドラインで設定する。compose upはdocker-compose.ymlで設定する。その違い。複数イメージの連動などをするなら、docker composeを使うしかなくなる。 | |||
execはイメージ内に入る。それ以外は、イメージを起動するという点で、根本的に違うので注意する。 | |||
==== | ==== build ==== | ||
===== ERROR: failed to build: failed to solve: DeadlineExceeded: failed to fetch anonymous token: Get ===== | |||
docker buildを実行すると以下のエラーが出ることがある。 | |||
$ docker build | |||
[+] Building 30.1s (3/3) FINISHED docker:default | |||
=> [internal] load build definition from Dockerfile 0.0s | |||
=> => transferring dockerfile: 3.32kB 0.0s | |||
=> ERROR [internal] load metadata for docker.io/library/composer:latest 30.0s | |||
=> ERROR [internal] load metadata for docker.io/library/php:7.4.0-apache 30.0s | |||
------ | |||
> [internal] load metadata for docker.io/library/composer:latest: | |||
------ | |||
------ | |||
> [internal] load metadata for docker.io/library/php:7.4.0-apache: | |||
------ | |||
Dockerfile:53 | |||
-------------------- | |||
51 | | |||
52 | # Composer install | |||
53 | >>> COPY --from=composer:latest /usr/bin/composer /usr/bin/composer | |||
54 | | |||
55 | # composer updateを実行 | |||
-------------------- | |||
ERROR: failed to build: failed to solve: DeadlineExceeded: failed to fetch anonymous token: Get "<nowiki>https://auth.docker.io/token?scope=repository%3Alibrary%2Fcomposer%3Apull&service=registry.docker.io</nowiki>": dial tcp 75.101.177.149:443: i/o timeout | |||
「[https://zenn.dev/headwaters/articles/b4abb757e31754 【久しぶりのDocker】 load metadata for docker.io/library/hoge:-alpine]」に記載通り、エラーになっているイメージ取得を事前にdocker pullで取得すると解決する。根本原因は不明。 | |||
docker pull php:7.4.0-apache | |||
docker pull composer | |||
==== docker run ==== | |||
docker buildで作ったイメージを実行するのがメインのコマンド。docker-composer.ymlを使わない場合に使う感じ。 | |||
docker container run --name sfcc-ex -it --rm -v ./:/var/www/html -v ./web2/:/var/www/html/web2/ -p 8080:80 sfcc-ex:latest | |||
-vでボリュームバインドして、イメージに名前を付けて実行する感じ。 | |||
=== Dockerfile === | |||
[https://docs.docker.com/reference/dockerfile/ Dockerfile reference | Docker Docs] | |||
==== RUN/CMD/ENTRYPOINTの違い ==== | ==== RUN/CMD/ENTRYPOINTの違い ==== | ||
| 202行目: | 353行目: | ||
ENTRYPOINTにコマンドを追記したい場合、entrypoint.shのようなスクリプトを実行する形にして、スクリプト内で引数処理するのがいいらしい。 | ENTRYPOINTにコマンドを追記したい場合、entrypoint.shのようなスクリプトを実行する形にして、スクリプト内で引数処理するのがいいらしい。 | ||
https://grok.com/share/c2hhcmQtMw%3D%3D_fa0e099c-4e70-4f24-8a80-cf68795fd0bb | |||
例えば、イメージ初回起動時だけ、composer installとかしたい場合、entprypoint.shに複雑な内容を記載して、それで実行する感じ。 | |||
#!/bin/bash | |||
# entrypoint.sh | |||
if [ ! -d "/app/vendor" ]; then | |||
echo "Running composer install..." | |||
composer install --no-interaction --prefer-dist | |||
else | |||
echo "Dependencies already installed." | |||
fi | |||
exec "$@" | |||
COPY entrypoint.sh /entrypoint.sh | |||
RUN chmod +x /entrypoint.sh | |||
ENTRYPOINT ["/entrypoint.sh"] | |||
CMD ["php-fpm"] | |||
===== 形式 ===== | |||
CMD/ENTRYPOINT/RUNではshellとexecの2種類の形式が許容される。 | |||
* <code>CMD ["executable","param1","param2"]</code> (exec form) | |||
* <code>CMD ["param1","param2"]</code> (exec form, as default parameters to <code>ENTRYPOINT</code>) | |||
* <code>CMD command param1 param2</code> (shell form) (/bin/sh -cを経由する) | |||
===== JSONArgsRecommended ===== | |||
2種類あるが、CMD/ENTRYPOINTではexec形式が推奨されているので、これらでは常にこの形式を使うべき。 | |||
1 warning found (use docker --debug to expand): | |||
- JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior related to OS signals (line 27) | |||
https://grok.com/share/c2hhcmQtMw%3D%3D_08a95e4b-fdab-44a1-b5d5-5bd44706256a | |||
[https://docs.docker.com/reference/build-checks/json-args-recommended/ JSONArgsRecommended | Docker Docs] | |||
使わないと上記の警告が出る。シェル形式だと、OSにシグナルが伝播しなくて、たとえばsleepしている場合、C-cで中断できない。 | |||
なお、exec形式でも、パイプや複合コマンド (&&, ||, ;) があると警告は解除されない。その場合、SHELLで事前に使用するSHELLを指定後、shell形式で記述する。 | |||
FROM alpine:latest | |||
# JSON形式(警告なし) | |||
SHELL ["sh", "-c"] | |||
CMD "echo 'Starting...' && sleep 30 && echo 'Done!'"] | |||
==== 権限設定 ==== | ==== 権限設定 ==== | ||
| 222行目: | 415行目: | ||
/root/.bashrcにumaskを指定する。これがないと、コマンドラインでdocker exec -i で実行した際デフォルトのumask 022でのファイル生成になり、この作業コマンドでログが発生したら、サーバープロセスから追記できない。 | /root/.bashrcにumaskを指定する。これがないと、コマンドラインでdocker exec -i で実行した際デフォルトのumask 022でのファイル生成になり、この作業コマンドでログが発生したら、サーバープロセスから追記できない。 | ||
FROM php:7.3.23-apache | FROM php:7.3.23-apache | ||
RUN apt update | RUN apt update ; apt install -y \ | ||
ssl-cert | ssl-cert | ||
RUN docker-php-ext-install pdo_mysql | RUN docker-php-ext-install pdo_mysql | ||
| 229行目: | 422行目: | ||
COPY --from=composer /usr/bin/composer /usr/bin/composer | COPY --from=composer /usr/bin/composer /usr/bin/composer | ||
ENV BASH_ENV /root/.bashrc | ENV BASH_ENV=/root/.bashrc | ||
RUN usermod -aG www-data root \ | RUN usermod -aG www-data root \ | ||
&& echo "umask 002" >>/root/.bashrc | && echo "umask 002" >>/root/.bashrc | ||
SHELL ["sh", "-c"] | |||
CMD chgrp -R www-data /var/www && chmod 2775 /var/www \ | CMD chgrp -R www-data /var/www && chmod 2775 /var/www \ | ||
&& find /var/www -type d -exec chmod 2775 {} \; \ | && find /var/www -type d -exec chmod 2775 {} \; \ | ||
| 246行目: | 440行目: | ||
他に上記にあるように、ENTRYPOINTでumaskを指定する方法がある。が、これは関係ない気がする。chomd 2775 /var/wwwでスティッキーを指定しているから、後続の作成時は自動で2775になっているはずだから。 | 他に上記にあるように、ENTRYPOINTでumaskを指定する方法がある。が、これは関係ない気がする。chomd 2775 /var/wwwでスティッキーを指定しているから、後続の作成時は自動で2775になっているはずだから。 | ||
==== 変数 ==== | |||
ARG/ENVで変数を展開でき、変数を参照可能。 | |||
* [https://docs.docker.com/reference/dockerfile/#using-arg-variables Using ARG variables | Dockerfile reference | Docker Docs] | |||
* [https://docs.docker.com/reference/dockerfile/#environment-replacement Environment replacement | ockerfile reference | Docker Docs] | |||
変数は $variable_name か ${variable_name} の形式で参照可能。 | |||
波括弧形式は、以下のbashの修飾子 (デフォルト値) も使用可能。 | |||
* ${variable:-word}: variableが未定義ならwordを返す。 | |||
* ${variable:+word}: variableが定義済みならwordを返す。 | |||
変数置換も可能。 | |||
* <code>${variable#pattern}</code> removes the shortest match of <code>pattern</code> from <code>variable</code>, seeking from the start of the string. | |||
* <code>${variable##pattern}</code> removes the longest match of <code>pattern</code> from <code>variable</code>, seeking from the start of the string. | |||
* <code>${variable%pattern}</code> removes the shortest match of <code>pattern</code> from <code>variable</code>, seeking backwards from the end of the string. | |||
* <code>${variable%%pattern}</code> removes the longest match of <code>pattern</code> from <code>variable</code>, seeking backwards from the end of the string. | |||
* <code>${variable/pattern/replacement}</code> replace the first occurrence of <code>pattern</code> in <code>variable</code> with <code>replacement</code> | |||
* <code>${variable//pattern/replacement}</code> replaces all occurrences of <code>pattern</code> in <code>variable</code> with <code>replacement</code> | |||
patternはglob。 | |||
<code>pattern</code> is a glob pattern where <code>?</code> matches any single character and <code>*</code> any number of characters (including zero). To match literal <code>?</code> and <code>*</code>, use a backslash escape: <code>\?</code> and <code>\*</code>. | |||
なお、CMD/ENTRYPOINT/RUNでは、Dockerの変数置換がうまく機能しない。 | |||
RUN echo ln -nfs /usr/local/instantclient_${VER/./_} /usr/local/instantclient | |||
RUN ["echo", "-nfs /usr/local/instantclient_${VER/./_} /usr/local/instantclient"] | |||
しかたないので、以下のように変数を用意しておく。 | |||
ARG VER=19.28 VER_=${VER/./_} | |||
==== ADD/COPY ==== | |||
Dockerイメージ内にファイルを取り込む指令。 | |||
セキュリティーの観点から、現在ディレクトリー以下のファイルか、URLしか取り扱えないので注意する。 | |||
=== Other === | |||
==== Docker on WSL2 ==== | |||
DockerのWindows版は有料ライセンスが必要。ただ、WSL経由だとライセンス不要。WSL経由でのDockerの使用方法を整理する。 | |||
以下のコマンドでwslをインストールする。 | |||
wsl --install | |||
実行中にUbuntuがインストールされる。その際にアカウントが求められるので入力する。 | |||
スタートメニュー[WSL] でWSL (Ubuntu) を起動できる。 | |||
後は、通常のDockerのインストール手順。 | |||
# Dockerのインストール | |||
sudo apt update | |||
curl <nowiki>https://get.docker.com</nowiki> | sh | |||
# docker-composeのインストール | |||
sudo apt install -y docker-compose | |||
# sudo なしで docker コマンドを利用できるようにする | |||
sudo usermod -aG docker $USER | |||
# Gitの設定もしておく | |||
git config --global user.name "" | |||
git config --global user.email "" | |||
これでWSL経由でDockerを使える。 | |||
VS Code経由で使う場合、工夫が必要。 | |||
WSL拡張機能をインストールする。タスクバー左下の接続マーク ([Open a Remote Window]) を選択-[WSLへの接続] を選ぶ。これでVSCodeがWSL経由になる。 | |||
==== CSRタイプのvolumeマウント ==== | |||
Webアプリのマウントの話。 | |||
一般的なWebアプリは公開ディレクトリーがpublicになっている。Apache HTTP ServerのデフォルトのDocumentRootは/var/www/html。これを踏襲する場合、docker/docker-composer.ymlは以下のような配置にする。 | |||
volumes: | |||
- ../:/var/www/ | |||
- ../public:/var/www/html | |||
ただ、CSR形式でfrontendとbackendをさらにディレクトリーで分けている場合、工夫が必要。 | |||
volumes: | |||
- ../backend/:/var/www/ | |||
- ../backend/public:/var/www/html | |||
- ../backend/:/var/backend | |||
- ../frontend/:/var/frontend | |||
こんな感じて/var/backend /var/frontendをマウントする。マウントしているだけで中身は同じ。 | |||
これで、frontend側でnpm run generateしても、そのままbackend/publicに配置できる。 | |||
==== docker runとexec ==== | ==== docker runとexec ==== | ||
| 307行目: | 587行目: | ||
ARG COMPOSER_AUTH | ARG COMPOSER_AUTH | ||
ENV COMPOSER_AUTH=${COMPOSER_AUTH} | ENV COMPOSER_AUTH=${COMPOSER_AUTH} | ||
==== ビルド時vs実行時 ==== | |||
https://grok.com/share/c2hhcmQtMw%3D%3D_fa0e099c-4e70-4f24-8a80-cf68795fd0bb | |||
Dockerで環境構築時に、例えばcomposer install、npm installのような初回パッケージインストールのような作業を、Dockerfile内に記載して、イメージビルド時実行するか、イメージ作成後の起動時に実行するか、判断がある。 | |||
* 再現性と一貫性 | |||
* ビルド効率とキャッシュ活用 | |||
* 開発と製品 | |||
* 操作の性質 | |||
一般的に、本番ではビルド時固定が推奨。開発ではビルド時installをしながら、ボリュームでオーバーライドする。 | |||
イメージ内にあるのにボリュームオーバーライドしていて二重になるが、まあ本番にもそのまま使うことを考えるとこうなる。 | |||
==== log ==== | |||
Dockerでイメージを作ると、/var/logとかが使えない。ログは別の場所に貯められている。 | |||
docker logsでログを閲覧できる。 | |||
phpのerror_logとかだと、以下のような書式になる。 | |||
[Fri Oct 03 01:49:59.742521 2025] [php7:notice] [pid 19] [client 172.17.0.1:50600] 7100018001 | |||
以下のコマンドのように絞り込むといい。 | |||
docker logs sfcc-ex | grep [php7 | |||
[[Category:IT]] | [[Category:IT]] | ||
2025年10月27日 (月) 11:43時点における最新版
UTM
Control
Capture
デフォルトだと、Control-Tabなど、一部のMac本体のホットキーが有効になっている。例えば、Windows側でc-tabを入力できなくて困る。
4番のボタンまたは、control-optionで、カーソルとキーボードをVMでキャプチャーする。これで入力可能になる。
Docker
Network
docker network ls
上記コマンドでコンテナーごとのネットワーク識別子を確認できる。コンテナー同士で同一ネットワークにするには、片方のservices.networks:でこのネットワーク識別子を指定する。
Compose
phpのアプリサーバー、DBサーバーを一つのイメージで作ることもできるが、別のイメージにして連動させることもできる。別のイメージ・コンテナーにしたほうが、管理しやすい模様。
docker composeで複数のイメージ・コンテナーを一体に管理できる。その際に、特有の事項がある。
PHPのPDOをDockerコンテナ内で使おうとしたところ、"No such file or directory" エラーが発生した話 #docker-compose - Qiita
docker composeで一体管理しているコンテナー群は、同一ネットワークに参加する。ホスト名はservice名になる。したがって、例えばアプリサーバーからDBサーバーへのアクセス時には、ホスト名に注意する。
How-tos
Use environment variables
Use environment variables | Docker Docs
Set environment variables within your container's environment
Set environment variables | Docker Docs
Interpolation
.envファイルで環境変数を渡せる。
Dockerfileにも渡すことができる。
https://chatgpt.com/c/673bedde-f5d0-800b-b604-fbb93c2dffe4
docker-compose.ymlのargsで引数として.envの環境変数を設定。
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
APP_ENV: ${APP_ENV}
ports:
- "${APP_PORT}:80"
Dockerfileで受け取って参照。
FROM php:8.1-cli
# ビルド引数を定義
ARG APP_ENV
# ビルド時の環境変数を設定
ENV APP_ENV=${APP_ENV}
# 確認用
RUN echo "App Environment: $APP_ENV"
WORKDIR /app
Image
PHP
Ref: php - Official Image | Docker Hub.
Dockerの公式PHPイメージを使う場合、いくつかPHP関係のライブラリーや拡張モジュールをインストール・設定するための専用コマンドが用意されている。
RUN pecl install memcached-3.2.0 \ && docker-php-ext-enable memcached
peclの拡張機能インストール時はバージョン指定が推奨される。
docker-php-ext-install
Docker で PHP 拡張モジュールをインストールする | QUARTETCOM TECH BLOG
PHP拡張モジュールのインストールと設定を行うヘルパーコマンドが用意されている。--helpで対象拡張モジュール一覧を確認できる。
$ docker run php:latest docker-php-ext-install --help # ..... Possible values for ext-name: bcmath bz2 calendar ctype curl dba dl_test dom enchant exif ffi fileinfo filter ftp gd gettext gmp hash iconv imap intl json ldap mbstring mysqli oci8 odbc opcache pcntl pdo pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell random readline reflection session shmop simplexml snmp soap sockets sodium spl standard sysvmsg sysvsem sysvshm tidy tokenizer xml xmlreader xmlwriter xsl zend_test zip # .....
PECL以外は一通り使用可能。
error
docker-php-ext-installでインストールする際には、必要な依存関係もセットで指定しないとエラーが出る。
FROM php:7.3.23-apache RUN apt update RUN docker-php-ext-install pdo_mysql RUN apt install -y libbz2-dev && docker-php-ext-install bz2 RUN apt install -y libpng-dev && docker-php-ext-install gd RUN apt install -y libzip-dev && docker-php-ext-install zip RUN apt install -y ssl-cert && a2enmod rewrite ssl && a2ensite default-ssl COPY --from=composer /usr/bin/composer /usr/bin/composer
ヘッダーのあるlib*-devもセットでインストールしておく。
Configuration
dockerのPHP公式イメージにはデフォルトのphp.iniとして、php.ini-development php.ini-productionの2種類が同梱されている。他に、$PHP_INI_DIR/conf.d/も追加されている。デフォルトからカスタマイズしたかったら、conf.dに追加する。
デフォルトのphp.iniとしてdevelopmentを使うといい。
RUN ln -fns php.ini-development "$PHP_INI_DIR/php.ini"
Composer
Docker に Composer をインストールするベストプラクティス(と解説) #PHP - Qiita
Docker 17.05以上になるが、以下をDockerファイルに記述するとOK。
COPY --from=composer /usr/bin/composer /usr/bin/composer
Dockerの公式イメージのcomposerから該当バイナリーだけをコピーして配置してくれる模様。
Oracleイメージ
FROM php:7.4.0-apache
ENV APACHE_DOCUMENT_ROOT /var/www/html
RUN apt-get update && apt-get install -y \
unzip \
libaio1
# custom php.ini
RUN echo "file_uploads = On\n" \
"memory_limit = -1\n" \
"upload_max_filesize = 500M\n" \
"post_max_size = 500M\n" \
"max_execution_time = 0\n" \
"output_buffering=4096\n" \
> /usr/local/etc/php/conf.d/custom.ini
# AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using xx.xx.xx.xx. Set the 'ServerName' directive globally to suppress this message
RUN echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf
RUN a2enconf fqdn
# Install Oracle Instantclient
ADD https://download.oracle.com/otn_software/linux/instantclient/214000/instantclient-basic-linux.x64-21.4.0.0.0dbru.zip /tmp
ADD https://download.oracle.com/otn_software/linux/instantclient/214000/instantclient-sdk-linux.x64-21.4.0.0.0dbru.zip /tmp
RUN unzip /tmp/instantclient-basic-linux.x64-21.4.0.0.0dbru.zip -d /usr/local/ && \
unzip /tmp/instantclient-sdk-linux.x64-21.4.0.0.0dbru.zip -d /usr/local/ &&\
ln -s /usr/local/instantclient_21_4 /usr/local/instantclient
ENV NLS_LANG=Japanese_Japan.JA16SJISTILDE
ENV LD_LIBRARY_PATH=/usr/local/instantclient
# Install Oracle extensions
RUN docker-php-ext-configure oci8 --with-oci8=instantclient,/usr/local/instantclient && \
docker-php-ext-install oci8 && \
docker-php-ext-configure pdo_oci --with-pdo-oci=instantclient,/usr/local/instantclient,21.4 && \
docker-php-ext-install pdo_oci && \
docker-php-ext-enable oci8
RUN rm -rf /tmp/*.zip
# Composer install
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# composer updateを実行
RUN chown www-data:www-data /var/www \
&& mkdir -p ${APACHE_DOCUMENT_ROOT}/vendor \
&& mkdir -p ${APACHE_DOCUMENT_ROOT}/var \
&& chown www-data:www-data ${APACHE_DOCUMENT_ROOT}/vendor \
&& chmod g+s ${APACHE_DOCUMENT_ROOT}/vendor
USER www-data
COPY composer.json ${APACHE_DOCUMENT_ROOT}/composer.json
#COPY composer.lock ${APACHE_DOCUMENT_ROOT}/composer.lock
RUN composer update \
--no-scripts \
--no-autoloader \
-d ${APACHE_DOCUMENT_ROOT} \
;
RUN composer dump-autoload
USER root
# Install Crypt_Blowfish
RUN pear install Crypt_Blowfish
# Install Smarty
# ADD https://github.com/smarty-php/smarty/archive/refs/tags/v3.1.39.zip /tmp
# RUN unzip /tmp/v3.1.39.zip -d /usr/local/ &&\
# ln -s /usr/local/smarty-3.1.39/libs /usr/local/lib/php/Smarty
# RUN rm -rf /tmp/*.zip
# DocumentRootを変更
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}/web2!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}/web2!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
phpmyadmin
Ref: phpmyadmin - Official Image | Docker Hub.
以下のdocker-compose.ymlを格納しておいて、networksのところをつなげたいやつにあわせる。
services:
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- 8080:80
environment:
- PMA_ARBITARY=1
networks:
- development_default
# - wordpress_default
networks:
wordpress_default:
external: true
development_default:
external: false
特に重要な環境変数。
PMA_ARBITRARY- when set to 1 connection to the arbitrary server will be allowed- PMA_HOST: デフォルトはdb。servicesがdb以外なら指定必要。
- PMA_USER/PMA_PASSWORD=phpmyadminのデフォルトユーザー。これを指定しておくと、自動ログインする。
MySQL
default
指定しなければrootのユーザーがデフォルトで用意される。
docker-compose.ymlで設定する場合、servicesで指定する名前がホスト名になる。これは127.0.0.1のところに記載が必要で忘れがちなので注意する。
phpで使う場合、以下の拡張機能が必要になる。
RUN docker-php-ext-install pdo_mysql
import
Ref: Import data.sql MySQL Docker Container - Stack Overflow.
docker exec -i mysql-container mysql -uuser -ppassword name_db < data.sql
上記のようなコマンドで取り込む。
apt update失敗対策
Dockerfile内でRUN apt update && apt installを実行すると以下のエラーが出る。
1.327 Err:6 http://deb.debian.org/debian bullseye-updates/main amd64 Packages 1.327 503 Service Unavailable [IP: 10.0.0.28 8080] 1.847 E: Failed to fetch http://deb.debian.org/debian/dists/bullseye-updates/main/binary-amd64/Packages 503 Service Unavailable [IP: 10.0.0.28 8080] 1.847 E: Some index files failed to download. They have been ignored, or old ones used instead.
/main/binary-amd64/Packagesのリポジトリーだけが503でアクセス不能になってエラーになっている。これのせいで、dockerがコマンドが失敗したとみなして、処理を中断している。ただ、このリポジトリーだけがエラーになっているだけで、他のリポジトリーは問題ない。
apt updateの失敗を無視してapt installを実行すると問題ない。
RUN apt update && apt install -y unzip
apt installの成否が大事なので。
Server
DocumentRootの変更
php - Official Image | Docker Hub
以下のような感じで設定ファイルを書き換える。
FROM php:7.1-apache
ENV APACHE_DOCUMENT_ROOT=/path/to/new/root
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
Error
connect ENOENT \\.\pipe\errorReporter
https://github.com/docker/for-win/issues/14080
再起動で直るらしい?
インストール時のアカウントの権限があるので、アカウント権限がある状態で再インストールするとOK。
`version` is obsolete
【docker compose】警告`version` is obsoleteの解決法
$ docker compose up time="2024-07-02T09:54:45+09:00" level=warning msg="C:\\Users\\senoo_0901\\project\\main\\GASProj\\docker\\docker-compose.yml: `version` is obsolete"
docker compose v2からversion指令は廃止になった。単純に削除すればいい。
Command
Docker コマンドラインを使う — Docker-docs-ja 24.0 ドキュメント
$HOME/.docker/config.json
Docker コマンドラインを使う — Docker-docs-ja 24.0 ドキュメント
プロキシー設定
プロキシ環境でdocker pullがうまくいかないときに試すこと | DevelopersIO
{
"proxies": {
"default": {
"httpProxy": "<プロキシURL>",
"httpsProxy": "<プロキシURL>"
}
}
}
これでDockerfile内でENV http_proxy=などを回避できる。
container
docker container | Docker Docs
exec/container run/compose up
よく似た概念のコマンドが複数あって混乱するので整理する。
- exec: 起動済みのコンテナーイメージ内に入る。
- container run/compose up: ほぼ同じ。イメージを起動する。container runはコマンドラインで設定する。compose upはdocker-compose.ymlで設定する。その違い。複数イメージの連動などをするなら、docker composeを使うしかなくなる。
execはイメージ内に入る。それ以外は、イメージを起動するという点で、根本的に違うので注意する。
build
ERROR: failed to build: failed to solve: DeadlineExceeded: failed to fetch anonymous token: Get
docker buildを実行すると以下のエラーが出ることがある。
$ docker build [+] Building 30.1s (3/3) FINISHED docker:default => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 3.32kB 0.0s => ERROR [internal] load metadata for docker.io/library/composer:latest 30.0s => ERROR [internal] load metadata for docker.io/library/php:7.4.0-apache 30.0s ------ > [internal] load metadata for docker.io/library/composer:latest: ------ ------ > [internal] load metadata for docker.io/library/php:7.4.0-apache: ------ Dockerfile:53 -------------------- 51 | 52 | # Composer install 53 | >>> COPY --from=composer:latest /usr/bin/composer /usr/bin/composer 54 | 55 | # composer updateを実行 -------------------- ERROR: failed to build: failed to solve: DeadlineExceeded: failed to fetch anonymous token: Get "https://auth.docker.io/token?scope=repository%3Alibrary%2Fcomposer%3Apull&service=registry.docker.io": dial tcp 75.101.177.149:443: i/o timeout
「【久しぶりのDocker】 load metadata for docker.io/library/hoge:-alpine」に記載通り、エラーになっているイメージ取得を事前にdocker pullで取得すると解決する。根本原因は不明。
docker pull php:7.4.0-apache docker pull composer
docker run
docker buildで作ったイメージを実行するのがメインのコマンド。docker-composer.ymlを使わない場合に使う感じ。
docker container run --name sfcc-ex -it --rm -v ./:/var/www/html -v ./web2/:/var/www/html/web2/ -p 8080:80 sfcc-ex:latest
-vでボリュームバインドして、イメージに名前を付けて実行する感じ。
Dockerfile
Dockerfile reference | Docker Docs
RUN/CMD/ENTRYPOINTの違い
Dockerfileでコマンドを実行する指令が複数ある。違いを整理する。
- RUN: イメージ作成時=docker build字に実行。ソフトウェアのパッケージインストール、ファイルコピー変更などを行う。
- CMD: コンテナ開始時=docker start、作成時=docker run時に実行される。docker run時のコマンドのデフォルト値。引数があればそちら優先。VolumeのバインドはRUN後になるのでCMD/ENTRYPOINTで行う必要がある。
- ENTRYPOINT: コンテナ開始時=docker start、作成時=docker run時に実行される。docker run時に強制実行。上書き不能。ただし、CMDや実行時に引数を後ろに追加できる。
CMD/ENTRYPOINTはDockerfile内でそれぞれ1回しか指定できない。一番最後の指定で上書きされる。
「The shell form of ENTRYPOINT prevents any CMD command line arguments from being used.」とあるように、 ENTRYPOINTとCMDを併用する場合、exec形式で指定しないとCMDが無視される。
「How to combine CMD and ENTRYPOINT - Open Source Projects / Compose - Docker Community Forums」
ENTRYPOINTにコマンドを追記したい場合、entrypoint.shのようなスクリプトを実行する形にして、スクリプト内で引数処理するのがいいらしい。
https://grok.com/share/c2hhcmQtMw%3D%3D_fa0e099c-4e70-4f24-8a80-cf68795fd0bb
例えば、イメージ初回起動時だけ、composer installとかしたい場合、entprypoint.shに複雑な内容を記載して、それで実行する感じ。
#!/bin/bash
# entrypoint.sh
if [ ! -d "/app/vendor" ]; then
echo "Running composer install..."
composer install --no-interaction --prefer-dist
else
echo "Dependencies already installed."
fi
exec "$@"
COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] CMD ["php-fpm"]
形式
CMD/ENTRYPOINT/RUNではshellとexecの2種類の形式が許容される。
CMD ["executable","param1","param2"](exec form)CMD ["param1","param2"](exec form, as default parameters toENTRYPOINT)CMD command param1 param2(shell form) (/bin/sh -cを経由する)
JSONArgsRecommended
2種類あるが、CMD/ENTRYPOINTではexec形式が推奨されているので、これらでは常にこの形式を使うべき。
1 warning found (use docker --debug to expand): - JSONArgsRecommended: JSON arguments recommended for CMD to prevent unintended behavior related to OS signals (line 27)
https://grok.com/share/c2hhcmQtMw%3D%3D_08a95e4b-fdab-44a1-b5d5-5bd44706256a
JSONArgsRecommended | Docker Docs
使わないと上記の警告が出る。シェル形式だと、OSにシグナルが伝播しなくて、たとえばsleepしている場合、C-cで中断できない。
なお、exec形式でも、パイプや複合コマンド (&&, ||, ;) があると警告は解除されない。その場合、SHELLで事前に使用するSHELLを指定後、shell形式で記述する。
FROM alpine:latest # JSON形式(警告なし) SHELL ["sh", "-c"] CMD "echo 'Starting...' && sleep 30 && echo 'Done!'"]
権限設定
Apache HTTP Serverの/var/wwwの権限設定 | GNU social JP Web
Why does chown not work in RUN command in Docker? - DevOps Stack Exchange
バインドボリュームする場合、RUNの後にバインドされるからCMDで設定が必要。
DockerfileにENTRYPOINTもCMDも無い?? | へるぷログ
CMD/ENTRYPOINTを指定しない場合、元イメージのCMD/ENTRYPOINTが実行される模様。apacheだとapache2-foregroundコマンド。
docker-composeでコンテナの初回起動時に特定の処理を行う方法 #Docker - Qiita
初回起動時に処理をする方法もあるが、一時ファイルを生成するなどするもの。権限設定は毎回実行してもOKなものなので、毎回実行する。
umask for non-root users not as expected · Issue #1142 · docker-library/php
/root/.bashrcにumaskを指定する。これがないと、コマンドラインでdocker exec -i で実行した際デフォルトのumask 022でのファイル生成になり、この作業コマンドでログが発生したら、サーバープロセスから追記できない。
FROM php:7.3.23-apache
RUN apt update ; apt install -y \
ssl-cert
RUN docker-php-ext-install pdo_mysql
RUN a2enmod rewrite ssl
RUN a2ensite default-ssl
COPY --from=composer /usr/bin/composer /usr/bin/composer
ENV BASH_ENV=/root/.bashrc
RUN usermod -aG www-data root \
&& echo "umask 002" >>/root/.bashrc
SHELL ["sh", "-c"]
CMD chgrp -R www-data /var/www && chmod 2775 /var/www \
&& find /var/www -type d -exec chmod 2775 {} \; \
&& find /var/www -type f -exec chmod 0664 {} \; \
&& apache2-foreground
docker exec実行時は、デフォルト実行されるコマンドはない。[Bash Startup Files (Bash Reference Manual)] にあるように、BASH_ENVに指定したファイルを非対話実行でも読み込むのでこれを指定して、常にbash -cで実行する。
あるいは、BASH_ENVを指定せずに、bash -c 'umask 002; 'で実行する。
- docker - Why is umask setting in dockerfile not working? - Stack Overflow
- Libertyコンテナでumaskを変える #Docker - Qiita
他に上記にあるように、ENTRYPOINTでumaskを指定する方法がある。が、これは関係ない気がする。chomd 2775 /var/wwwでスティッキーを指定しているから、後続の作成時は自動で2775になっているはずだから。
変数
ARG/ENVで変数を展開でき、変数を参照可能。
- Using ARG variables | Dockerfile reference | Docker Docs
- Environment replacement | ockerfile reference | Docker Docs
変数は $variable_name か ${variable_name} の形式で参照可能。
波括弧形式は、以下のbashの修飾子 (デフォルト値) も使用可能。
- ${variable:-word}: variableが未定義ならwordを返す。
- ${variable:+word}: variableが定義済みならwordを返す。
変数置換も可能。
${variable#pattern}removes the shortest match ofpatternfromvariable, seeking from the start of the string.${variable##pattern}removes the longest match ofpatternfromvariable, seeking from the start of the string.${variable%pattern}removes the shortest match ofpatternfromvariable, seeking backwards from the end of the string.${variable%%pattern}removes the longest match ofpatternfromvariable, seeking backwards from the end of the string.${variable/pattern/replacement}replace the first occurrence ofpatterninvariablewithreplacement${variable//pattern/replacement}replaces all occurrences ofpatterninvariablewithreplacement
patternはglob。
pattern is a glob pattern where ? matches any single character and * any number of characters (including zero). To match literal ? and *, use a backslash escape: \? and \*.
なお、CMD/ENTRYPOINT/RUNでは、Dockerの変数置換がうまく機能しない。
RUN echo ln -nfs /usr/local/instantclient_${VER/./_} /usr/local/instantclient
RUN ["echo", "-nfs /usr/local/instantclient_${VER/./_} /usr/local/instantclient"]
しかたないので、以下のように変数を用意しておく。
ARG VER=19.28 VER_=${VER/./_}
ADD/COPY
Dockerイメージ内にファイルを取り込む指令。
セキュリティーの観点から、現在ディレクトリー以下のファイルか、URLしか取り扱えないので注意する。
Other
Docker on WSL2
DockerのWindows版は有料ライセンスが必要。ただ、WSL経由だとライセンス不要。WSL経由でのDockerの使用方法を整理する。
以下のコマンドでwslをインストールする。
wsl --install
実行中にUbuntuがインストールされる。その際にアカウントが求められるので入力する。
スタートメニュー[WSL] でWSL (Ubuntu) を起動できる。
後は、通常のDockerのインストール手順。
# Dockerのインストール sudo apt update curl https://get.docker.com | sh # docker-composeのインストール sudo apt install -y docker-compose # sudo なしで docker コマンドを利用できるようにする sudo usermod -aG docker $USER # Gitの設定もしておく git config --global user.name "" git config --global user.email ""
これでWSL経由でDockerを使える。
VS Code経由で使う場合、工夫が必要。
WSL拡張機能をインストールする。タスクバー左下の接続マーク ([Open a Remote Window]) を選択-[WSLへの接続] を選ぶ。これでVSCodeがWSL経由になる。
CSRタイプのvolumeマウント
Webアプリのマウントの話。
一般的なWebアプリは公開ディレクトリーがpublicになっている。Apache HTTP ServerのデフォルトのDocumentRootは/var/www/html。これを踏襲する場合、docker/docker-composer.ymlは以下のような配置にする。
volumes:
- ../:/var/www/
- ../public:/var/www/html
ただ、CSR形式でfrontendとbackendをさらにディレクトリーで分けている場合、工夫が必要。
volumes:
- ../backend/:/var/www/
- ../backend/public:/var/www/html
- ../backend/:/var/backend
- ../frontend/:/var/frontend
こんな感じて/var/backend /var/frontendをマウントする。マウントしているだけで中身は同じ。
これで、frontend側でnpm run generateしても、そのままbackend/publicに配置できる。
docker runとexec
docker runとdocker execの違いの解説 | めもたんす
run: イメージ作成・実行。
exec: 起動中のイメージで実行。
Japanese input/日本語入力
OSに日本語のロケールが入っていないのが原因。
Debian系の場合。
## For Japanese input. RUN apt install -y locales RUN (rm /etc/locale.gen && sed '/# ja_JP.UTF-8 UTF-8/s/# //' >/etc/locale.gen) </etc/locale.gen RUN locale-gen ENV LANG=ja_JP.UTF-8
/etc/locale.genのファイルの修正が必要。
これで日本語が使用可能になる。
cron
How to run a cron job inside a docker container? - Stack Overflow
Docker内でcronを実行する方法がいくつかある。
## For cron. RUN apt install -y cron RUN (crontab -l ; echo '* * * * * /usr/local/bin/php /var/www/artisan schedule:run >/dev/null 2>&1') | crontab CMD cron # CMDは最後の1個しか有効じゃないので、最後にまとめて指定することに注意する。
動作確認
crontab -l # crontabの確認 pgrep cron # cronプロセスの確認
認証情報
composerでプライベートリポジトリーをinstallしようとすると少々厄介。
https://chatgpt.com/c/673bedde-f5d0-800b-b604-fbb93c2dffe4
いくつか方法がある。.envに認証情報を記入して、それを参照するのがシンプル。
.env
COMPOSER_AUTH='{"github-oauth":{"github.com":"YOUR_TOKEN"}}'
github.comの[Settings]-[Developer settings]-[Personal access tokens]-[[Tokens (classic)](https://github.com/settings/tokens)]-[Generate new token] から作成した新しいトークンを記入しておく ([Select scopes]=[repo] を最低チェック)
docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
args:
COMPOSER_AUTH: ${COMPOSER_AUTH}
volumes:
- .:/app
Dockerfile
ARG COMPOSER_AUTH
ENV COMPOSER_AUTH=${COMPOSER_AUTH}
ビルド時vs実行時
https://grok.com/share/c2hhcmQtMw%3D%3D_fa0e099c-4e70-4f24-8a80-cf68795fd0bb
Dockerで環境構築時に、例えばcomposer install、npm installのような初回パッケージインストールのような作業を、Dockerfile内に記載して、イメージビルド時実行するか、イメージ作成後の起動時に実行するか、判断がある。
- 再現性と一貫性
- ビルド効率とキャッシュ活用
- 開発と製品
- 操作の性質
一般的に、本番ではビルド時固定が推奨。開発ではビルド時installをしながら、ボリュームでオーバーライドする。
イメージ内にあるのにボリュームオーバーライドしていて二重になるが、まあ本番にもそのまま使うことを考えるとこうなる。
log
Dockerでイメージを作ると、/var/logとかが使えない。ログは別の場所に貯められている。
docker logsでログを閲覧できる。
phpのerror_logとかだと、以下のような書式になる。
[Fri Oct 03 01:49:59.742521 2025] [php7:notice] [pid 19] [client 172.17.0.1:50600] 7100018001
以下のコマンドのように絞り込むといい。
docker logs sfcc-ex | grep [php7
