既存webシステムのコンテナ化(1) Docker実践-2
WSL2(debian latest)を使って既存のシステムのコンテナ化をしてみようと思う。 開発環境の構成は次の通り。
Windows10 professional WSL2 (debian latest) Docker (20.10.17)
開発環境の構築手順はこちら damienkarrus.hatenablog.com
コンテナ化する対象のシステムは、CentOS7+Apache2+PHP7+PostgreSQL14で動作し、顧客用webページと、コンテンツ管理用の管理者ページがあり、それぞれURIを持っているが同一サーバで稼動している。DBは双方のwebページからアクセスされている。永続的に保存しなければいけないデータは、データベース、ユーザアップロードファイルである。 デバッグの効率性を考えて、PHPのソースはWindows上のフォルダに置き、それをdebianが勝手にマウントしてくれるので、そのdebianのディレクトリをコンテナがbindして使う。デバッグ完了後は、bindせずに、コンテナ内にソースファイルを保持するようyamlに定義することにする。
Windowsフォルダのマウント状況は当環境では次のようになった。
Windows: X:\oto\public_html ←管理者向けwebページ X:/rega/public_html ←顧客向けwebページ X:\oto\files ←アップロードされたファイル ↓ WSL( WSL2(debian): /mnt/x/oto/public_html /mnt/x/rega/public_html /mnt/x/oto/files
フォルダ構成
作業フォルダ(oto)を作成し、配下にDBとウェブアプリ(apache+php)のサブフォルダを作って、イメージはそれぞれの中でDockerfileで定義しておき、全体をdocker-composeでコントロールする。また、webサーバは一般公開用(web)とコンテンツ管理用(web2)があるので、2つのコンテナを用意し、それぞれがDBコンテナ、外部ボリュームコンテナを参照するように構築する。 oto下のファイル、ディレクトリ構成は以下の通り
docker-compose.yaml postgres/ web/ web2/
postgres
postgresフォルダ内は
Dockerfile docker-entrypoint-initdb.d/
Dockerfileは
FROM postgres:14-alpine ENV LANG ja_JP.utf8 ENV TZ=Asia/Tokyo
docker-entrypoint-initdb.d には、データベースの初期データを data.out というファイル名でおいておくことにする(後ほどリストアして使用する)。
Postgresのデータはボリュームを作成しておきvolumeマウントして使う。
$ docker volume create --name oto-db
web , web2
webフォルダ / web2フォルダは
Dockerfile php.ini apache2.conf
phpの設定ファイルはbindして使用する(デバッグ・調整のため)。apacheはlatest、phpは7.4を指定した。 アップロードされたデータの保存先はボリュームを作成しておきvolumeマウントして使う。
$ docker volume create --name oto-files
Dockerfileは
FROM debian ENV TZ=Asia/Tokyo EXPOSE 80 RUN apt-get update RUN apt-get install -y sudo RUN apt-get install -y curl ca-certificates gnupg \ && sudo apt-get install -y build-essential apt-transport-https \ && sudo apt-get install -y php7.4 php7.4-intl php7.4-mbstring php7.4-pgsql php7.4-fpm php7.4-cli php7.4-zip \ && sudo apt-get install -y apache2 libapache2-mod-php \ && sudo apt-get install -y iputils-ping net-tools dnsutils \ ←疎通確認などに使用するツール && sudo apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && rm /var/www/html/index.html COPY apache2.conf /etc/apache2/ CMD /usr/sbin/apachectl -DFOREGROUND STOPSIGNAL SIGWINCH
php.iniは
[PHP] post_max_size = 1024M upload_max_filesize = 1024M max_file_uploads = 20 [Date] date.timezone = "Asia/Tokyo" [mbstring] mbstring.internal_encoding = "UTF-8" mbstring.language = "Japanese" ↑色々足りていないが、動作確認にはこれでOK
docker-compose
docker-compose.yamlは
version: '3' services: web: build: ./web ports: - 8080:80 volumes: - ./web/php.ini:/usr/local/etc/php/php.ini - /mnt/x/oto/public_html:/var/www/html - oto-files:/var/www/html/files web2: build: ./web2 ports: - 8081:80 volumes: - ./web2/php.ini:/usr/local/etc/php/php.ini - /mnt/x/rega/public_html:/var/www/html - oto-files:/var/www/html/files db: build: ./postgres ports: - 5432:5432 environment: POSTGRES_USER: admin POSTGRES_PASSWORD: admin volumes: - ./postgres/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d - oto-db:/var/lib/postgresql/data volumes: oto-db: external: true oto-files: external: true
build前に既存システムのdbのバックアップを取り、postgres/docker-entrypoint-initdb.dに保存しておく
(既存システムで) pg_dump cpan69 > data.out
このファイルをpostgres/docker-entrypoint-initdb.d内にコピーしておく。
buildしてみる
$ docker-compose up --build -d Building web [+] Building 7.2s (11/11) FINISHED ...(snip)... Creating oto_db_1 ... done Creating oto_web2_1 ... done Creating oto_web_1 ... done
稼働状況を確認する
$ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------ oto_db_1 docker-entrypoint.sh postgres Up 0.0.0.0:5432->5432/tcp oto_web2_1 /bin/sh -c /usr/sbin/apach ... Up 0.0.0.0:8081->80/tcp oto_web_1 /bin/sh -c /usr/sbin/apach ... Up 0.0.0.0:8080->80/tcp
コンテナ構築後の諸作業
疎通確認をする。まずはwebサーバにログインする。
$ docker container exec -it oto_web_1 /bin/bash
dbサーバにpingしてみる
# ping db PING db (192.168.160.2) 56(84) bytes of data. 64 bytes from oto_db_1.oto_default (172.18.0.2): icmp_seq=1 ttl=64 time=0.081 ms ...(snip)...
DBのリストア
バックアップファイルをリストアする。dbサーバにログインする。
$ docker container exec -it oto_db_1 /bin/bash
DBに移植元のユーザとapache2のユーザを登録して、リストアし、apache2に対してgrant allをかける
# cd /docker-entrypoint-initdb.d # createuser cpan69 ※現行システムがユーザcpan69で運用されているため、リストア時のエラー回避の為作成 # createuser www-data ※apache2のデフォルトユーザ名 # createdb cpan69 # psql -U admin cpan69 < data.out # psql -U admin cpan69 < grantall.sql ※grant all on テーブル名 to www-data を記述したファイル
ソースファイルの修正
PostgreSQLのopenパラメータの調整 コンテナ化前はlocalhostを参照していたためhost指定を追加し、アクセスユーザも指定する。
$handler=pg_pconnect("dbname=$db_name");//コンテナ化前の記述 ↓ $handler=pg_pconnect("host=db dbname=$db_name user=admin password=admin");
アップロード済みファイルを外部ボリュームへ展開する
元データのtarボールをソースファイルと同じところにおいておき、外部コンテナがマウントされている場所にて展開する
まずはwebサーバにログインする。
$ docker container exec -it oto_web_1 /bin/bash
tarボールを展開する
# cd /var/www/html/files # tar xf /var/www/html/msheet.tar . # cd msheet # cdmod 757 . ※apacheから書き込みが出来るよう許可 # chown www-data:www-data *.pdf ※apacheが書き込んだデータなのでオーナーをwww-dataに変更
ブラウザでlocalhostの8080と8081にアクセスし動作を確認する。
cronの設定
次にcrontabにスケジュールを登録する。実はここではまった。いつもはredhat系でcrontabにスケジュールを登録していたのだが、これでは時刻になっても発火しない。debian系だから?コンテナだから?ネットで検索するとbusyboxのcrondが良いとある。動作しない原因が不明なのは気持ち悪いが原因究明は別の機会にするとして、ここでは動作するものをインストールして使用することにする。 まずはモジュールをインストールするため、Dockerfileの記述を書き足す。
FROM debian ENV TZ=Asia/Tokyo EXPOSE 80 RUN apt-get update RUN apt-get install -y sudo RUN apt-get install -y curl ca-certificates gnupg \ && sudo apt-get install -y build-essential apt-transport-https \ && sudo apt-get install -y php7.4 php7.4-intl php7.4-mbstring php7.4-pgsql php7.4-fpm php7.4-cli php7.4-zip \ && sudo apt-get install -y apache2 libapache2-mod-php \ && sudo apt-get install -y iputils-ping net-tools dnsutils \ && sudo apt-get install -y busybox-static \ ←これでcrondがインストールされる && sudo apt-get install -y vim \ ←viもインストールしておく && sudo apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /var/www/html/* \ && rm -rf /var/www/html/files COPY apache2.conf /etc/apache2/ COPY crontab /var/spool/cron/crontabs/www-data ←crontabのコピー CMD busybox crond -l 2 -L /dev/stderr -f & ←crondの起動 ※起動しない CMD /usr/sbin/apachectl -DFOREGROUND STOPSIGNAL SIGWINCH
crontabの内容は次の通り
00 11 * * * /bin/bash /var/www/html/cron.sh 00 07 * * 1 php /var/www/html/cli_shift_request_clear.php
※crondが起動しない。&を付けてもつけなくても起動しない。仕方ないので手動で起動した。
$ docker container exec -it otona_web_1 /bin/bash root@d984e2b3e681:/# busybox crond -l 2 -L /dev/stderr -f &
※なお、EWSのEC2でdocker-composeすると、Dockerfile内にEXPOSE 80の記述があると、pullするときに404エラーになり落ちる
ここまでで、辛うじてコンテンツ自体はコンテナ化ができた。 次に定期的なバックアップをやってみる。 「既存webシステムのコンテナ化(2)」(現在作成中)に続く。