更新: firewalld の設定に誤りがあったので修正しました。
更新2: php のイメージに gd の jpeg と imagick を追加しました
更新3: firewalld の許可設定は不要でした
CentOS 6 のサポート期限が迫ってきているので CentOS 8 について必死で勉強しています。試しに全部コンテナで環境作ろうとしたのですが、CentOS 8 は docker ではなく podman が標準っぽいので、試しに podman で web サーバーを立ち上げてみました。
主力の PC が Windows なので Hyper-V で CentOS 8 を立ち上げて試しています(なので、 Hyper-V 専用の手順が紛れている可能性がありますがご承知おきください)。podman は docker と互換性があるので、 docker コマンドを podman に置き換えればほぼそのまま動くようです。
今回使用するイメージは以下の3つです。
podman でも Docker Hub からイメージをプルできます。
podman の目玉機能として、 rootless (ルート以外のユーザー)でコンテナ実行できる機能があるのですが、今回は 80 番ポートを使いたかったので rootfull で構築します。
SELinux が有効な場合は盛大にブロックしてくるので、先に setenforce 0 にしておき、後でポリシーを作りましょう(本記事では割愛)。また、 sudo 付けるのが面倒なので、root でログインして作業する想定で書いています。root 権限必須ですので、環境に合わせて sudo 付けてください。
PHP イメージの作成
php に関しては php の extension を入れないといけないので Dockerfile を書いてイメージを作る必要があります。podman でも Dockerfile なんですね。私はイメージ作成用のファイルをユーザーホームに作るタイプなので、/root/php/Dockerfileに以下のファイルを配置しました。必要な拡張は docker-php-ext-install コマンドを使用してインストールします。
また、拡張をビルドするために必要なパッケージを apk add に指定する必要があります。alpine Linux をベースにしているので、パッケージ管理は apk を使用します。dnf, apt-get とはパッケージ名が違う場合があるので注意が必要です。必要な物は php のドキュメントに書いてありますが、私は面倒なのでエラーが出たら追加する方針で書いてます。
shadow は usermod, groupmod コマンドを入れるために指定しているパッケージです。
FROM php:fpm-alpine
RUN apk add --update --no-cache oniguruma-dev curl-dev \
icu-dev libpng-dev jpeg-dev giflib-dev shadow \
imagemagick-dev autoconf make g++ libzip-dev freetype-dev
RUN docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/
RUN docker-php-ext-install mbstring \
curl intl gd mysqli pdo_mysql opcache \
zip exif
RUN pecl install imagick
RUN docker-php-ext-enable imagick
ARG UID=1000
ARG GID=1000
RUN usermod -u $UID www-data
RUN groupmod -g $GID www-dataイメージを作成する前に、 www-data ユーザー&グループをホスト側に作っておきます。php fpm イメージでは www-data ユーザーで php を実行するので、ホスト側とコンテナ側で同じユーザー名&UIDに揃えておいた方が便利なためです。
useradd -M www-dataDockerfile を配置したディレクトリに移動し、 buildah コマンドを打ちイメージを作成します。buildah はイメージ作成用のツールです。最初から CentOS 8 に入っていました。Dockerfile を置いたディレクトリで実行してください。
buildah bud \
--build-arg UID=$(id -u www-data) \
--build-arg GID=$(id -g www-data) \
--tag my-php .完了後に buildah imagesコマンドをたたくと localhost/my-phpイメージができているのが確認できます。
pod の作成
pod を作成します。pod はコンテナをまとめるグループのようなものです。ネットワーク的に良さそう(localhost でコンテナ間通信できる)だったので、pod でまとめることにしました。
pod はポートなどインフラ部分を複数のコンテナで共有します。ですのでポートフォワーディングの設定は pod を立ち上げる際に実施します。
podman pod create -p 80:80 -p 443:443 -p 3306:3306 -n wwwpodポート番号のマッピングを変えたい場合は、左側の数字を変更します。-p host:containerです。
コンテナで使用するディレクトリの作成
場所は任意ですが、今回はコンテナ関係のファイルを /srvに置くことにしました。設定やデータ系を置く場所です。
mkdir --parents \
/srv/wwwpod/mariadb/data \
/srv/wwwpod/nginx/config \
/srv/wwwpod/php/config \
/srv/wwwpod/public/srv/wwwpod/
├── mariadb
│ └── data
├── nginx
│ └── config
├── php
│ └── config
└── publicpublic は web ページのファイルを置く場所なので、 www-data ユーザー&グループを所有者にしておきます。php が www-data ユーザーで実行されるので、読み書きできるようにしておく必要があるためです。
chown www-data:www-data -R /srv/wwwpod/publicmariadb コンテナの立ち上げ
mariadb を立ち上げます。my-secret-pwは root のパスワードなので変更してください。
podman run --detach \
--pod wwwpod \
--name mariadb \
--restart always \
--volume /srv/wwwpod/mariadb/data:/var/lib/mysql \
--env MYSQL_ROOT_PASSWORD=my-secret-pw \
--log-driver journald \
mariadb標準のログドライバーは k8s-file なのでログファイルが出力されるのですが、ログローテーションの説明を見つけられず不安だったので journald を指定しておきます。
php コンテナの立ち上げ
php の設定ファイルを持ってきます。extension の読み込み設定は、 docker-php-ext-install コマンドにより自動で追加されるので不要です。
podman run --name tmp-php -d localhost/my-php
podman cp tmp-php:/usr/local/etc/php/php.ini-production
/srv/wwwpod/php/config/php.ini
podman rm -f tmp-phpphp を立ち上げます。
podman run --detach \
--pod wwwpod \
--name php \
--volume /srv/wwwpod/php/config/php.ini:/usr/local/etc/php/php.ini:ro \
--volume /srv/wwwpod/public:/usr/share/nginx/html \
--log-driver journald \
localhost/my-phpnginx コンテナの立ち上げ
まずは nginx の設定ファイルを持ってきます。
podman run --name tmp-nginx -d nginx
podman cp tmp-nginx:/etc/nginx/nginx.conf /srv/wwwpod/nginx/config/nginx.conf
podman cp tmp-nginx:/etc/nginx/conf.d/default.conf /srv/wwwpod/nginx/config/conf.d/default.conf
podman rm -f tmp-nginx/srv/wwwpod/nginx/config/conf.d/default.conf を編集し、 php を実行できるようにします。
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.php index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
location ~ \.php$ {
root /usr/share/nginx/html;
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
}nginx を立ち上げます。
podman run --detach \
--pod wwwpod \
--name nginx \
--volume /srv/wwwpod/nginx/config/nginx.conf:/etc/nginx/nginx.conf:ro \
--volume /srv/wwwpod/nginx/config/conf.d:/etc/nginx/conf.d:ro \
--volume /srv/wwwpod/public:/usr/share/nginx/html:ro \
--log-driver journald \
nginxコンテナ立ち上げ後に設定ファイルを修正した場合は、 reload コマンドを実行します。
podman exec nginx nginx -s reloadnginx が2つ並んでるのは間違いではないです。nginx コンテナの nginx コマンドを実行します。
net.ipv4.ip_forward を設定
デフォルトの状態だとコンテナからインターネットが見れなかったので以下のコマンドを打ちました。
sysctl -w net.ipv4.ip_forward=1
cat <<EOF > /etc/sysctl.d/podman.conf
net.ipv4.ip_forward=1
EOFweb ページの配置
/srv/wwwpod/public に html や php ファイルを置けば見えるようになるはずです。試しに Wordpress を置いて軽く動かしてみましたが、大丈夫そうです。少なくとも記事の投稿やプラグインのインストールは可能でした。
firewalld の設定
この章は設定不要でした。firewalld の拒否設定より先にポートフォワーディングが適用されるので、ポートマッピングしただけで外から見えます。
外部に公開する場合は firewall-cmd を使って許可するポートを指定します。
firewall-cmd --zone=public --add-port=8080/tcp
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --zone=public --add-service=https
firewall-cmd --zone=public --add-service=https --permanent--permanent ありの場合は firewall-cmd --reload も必要ですが、 reload をするとコンテナの再起動が必要になります(コンテナが起動時に自動設定したルールが消える。)。そのため、--permanent オプションあり(恒久的に反映)となし(即時反映)を両方実行します。
その他
診断
何か問題が起きた時に調査する方法です。
実行中のコンテナを見る場合は以下のコマンドを使用します。
podman ps各コンテナの shell に入る場合は以下のコマンドを打ちます。php だけ alpine なので bash が入っていないです。
podman exec -it nginx bash
podman exec -it php sh
podman exec -it mariadb bash各コンテナのログを見る場合は以下のコマンドを打ちます。
podman logs -f nginx
podman logs -f php
podman logs -f mariadbコンテナの立ち上げ、停止
pod ごとまとめて開始・停止したり、コンテナごとに開始・停止したりできます。
podman pod start wwwpod
podman start nginx
podman start php
podman start mariadbpodman pod stop wwwpod
podman stop nginx
podman stop php
podman stop mariadb課題
お試しなので権限回りの設定や動作確認が甘めです。
- nginx と mariadb も UID GID そろえた方がよさそう
- nginx はデフォルトだと UID=101 GID=101 で動く
- mariadb (mysqld) は UID=999 GID=999 で動く
- ✔ php と nginx のワーカープロセス、 mariadb 以外は root で動くので、SELinux を適切に設定したほうがよさそう
chcon -Rt container_file_t /srv/wwwpodで許可できる- コンテナを複数立ち上げる場合は MCS の設定も考える必要がありそう
- こちらの記事にまとめました
- ✔ インターネット側からアクセスできるかの確認 → 確認しました
- ✔ ホスト起動時にコンテナも立ち上げる方法 → こちらの記事にまとめました
- mariadb の設定ファイルもホスト側に置く
- ✔ 存在しない php ファイルへアクセスすると「 File not found. 」画面が出てしまう → 本記事を修正しました
- ✔ podman のネットワークが初期設定だと IPv6 の通信を受けられない → こちらの記事にまとめました
バージョン情報
今回使用した podman のバージョンです。
podman version 1.6.4
buildah version 1.11.6