CentOS 7 + Apache + php-fpm + mariaDB でdocker-compose環境を作る


はじめに

業務で使用しているのがCentOSなので公式のphpイメージがあるかと探して見たんですが、
公式のイメージはDebianなのでdocker-composeでCentOSのLAMP環境を作成しました。

せっかくなのでネットでよくみるApacheのコンテナ内に直接PHPをインストールする形ではなく
php-fpm用の別コンテナを立てて各コンテナを連携します。

完成品はこちら

手順はいいから現物はよっ!という方はこちらのリポジトリにあります。
temori1919/docker-lamp

構成

ディレクトリ構造

docker-lamp/
├── web
│   ├── logs
│   ├── Dockerfile
│   └── docker.conf  #[/etc/httpd/conf.d]にコピーするconfファイル
├── php
│   ├── xdebug.ini   #[/usr/local/etc/php/conf.d]にコピーするphp.iniファイル
│   └── Dockerfile
├── db
│   ├── logs
│   ├── my.cnf     #[/etc/mysql/conf.d]にコピーするmysql confファイル
│   └── Dockerfile
├── code             codeの下がドキュメントルート([/var/www/html]にマウントされる)
│   ├── example
|   ├── gulpfile.js
│   └── config
|      └── default.json.example
└── docker-compose.yml

docker-compose.yml

version: '3.7'
services:
  # centos7 apache2.4.*(http2)
  web:
    build: ./web
    ports:
      - '80:80'
      - '443:443'
    depends_on:
      - php
    volumes:
      - ./code:/var/www/html
      - ./web/logs:/var/log/httpd
      - cert:/etc/ssl/private
    restart: always
    env_file: .env
  # php-fpm 
  php:
    build: ./php
    depends_on:
      - db
    ports:
      - '9000'
    volumes:
      - ./code:/var/www/html
    restart: always
    env_file: .env
  # mariaDB
  db:
    build: ./db
    restart: always
    env_file: .env
    ports:
      - 3306:3306
    volumes:
    - ./db/logs:/var/log/mysql
    - datastore:/var/lib/mysql
  # phpMyadmin
  phpmyadmin:
    depends_on:
      - db
    image: phpmyadmin/phpmyadmin
    env_file: .env
    ports:
     - 8080:80
  # php Composer
  composer:
    image: composer
  # node js (include gulp)
  node:
    build: ./node
    restart: always
    tty: true
    ports:
      - '8081'
    depends_on:
      - web
    volumes:
      - ./code:/var/www/html

volumes:
  cert:
  datastore:

1.CentOS + Apacheコンテナ

Dockerfile

FROM centos:7
RUN yum update -y
RUN yum -y remove httpd httpd.x86_64 httpd-tools.x86_64

# install leatest apache2.4.*
RUN yum install -y epel-release && \
    yum -y install https://centos7.iuscommunity.org/ius-release.rpm && \
    sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/ius.repo && \
    sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/epel.repo
RUN yum --enablerepo=epel -y install nghttp2 && \
    yum -y install epel-release && \
    yum -y install mailcap system-logos && \
    yum -y install openssl && \
    yum -y --disablerepo=base,extras,updates --enablerepo=ius install httpd mod_ssl && \
    yum clean all
RUN sed -i -e "s|LoadModule mpm_prefork_module modules/mod_mpm_prefork.so|#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so|" /etc/httpd/conf.modules.d/00-mpm.conf && \
    sed -i -e "s|#LoadModule mpm_event_module modules/mod_mpm_event.so|LoadModule mpm_event_module modules/mod_mpm_event.so|" /etc/httpd/conf.modules.d/00-mpm.conf
# make SSL server certificate
RUN mkdir -p /etc/ssl/private && \
    openssl req -new -newkey rsa:2048 -nodes -out /etc/ssl/private/server.csr -keyout /etc/ssl/private/server.key -subj "/C=/ST=/L=/O=/OU=/CN=*.lvh.me" && \
    openssl x509 -days 3650 -req -signkey /etc/ssl/private/server.key -in /etc/ssl/private/server.csr -out /etc/ssl/private/server.crt

COPY docker.conf /etc/httpd/conf.d/docker.conf

# dockre can not use systemd without permission, apahce is started with httpd
CMD ["/usr/sbin/httpd", "-DFOREGROUND"]

今回の要件ではPHPを別コンテナ立てする予定なので、Apacheのconfファイルで.phpのファイルだけをphp-fpmのコンテナで動かしたかった。

当初は「ProxyPassMatch」を使ってphp拡張子のファイルをphp-fpmコンテナで動かそうと思っていましたが、以下のような問題点があるようです。

(ファイルシステムと関係がないプロクシーなので) DirectoryIndex が効かない
(同じ理由で) .htaccess によるディレクトリごとの制御ができない
PATH_INFO がおかしい。そのため PHP の PHP_SELF サーバー変数もおかしい
PHP :: Bug #65641 :: PHP-FPM incorrectly defines the SCRIPT_NAME variable when using Apache

誰かの役に立てばいいブログ

Apache2.4.10以上のインストール

そこでApache2.4.10以上で書けるようになったFilesMatchディレクティブを使用します。

CentOS7のyumでApacheをインストールすると2.4.6が入ってしまうので、
Apacheのリポジトリを追加します。

# この辺りの記述
yum -y install https://centos7.iuscommunity.org/ius-release.rpm && \
    sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/ius.repo && \
    sed -i -e "s/enabled *= *1/enabled=0/g" /etc/yum.repos.d/epel.repo
RUN yum --enablerepo=epel -y install nghttp2 && \
    yum -y install epel-release && \
    yum -y install mailcap system-logos && \
    yum -y install openssl && \
    yum -y --disablerepo=base,extras,updates --enablerepo=ius install httpd mod_ssl && \
    yum clean all

ついでにオレオレ証明も使いたいので、opensslやmod_sslモジュールも入れておきます。

2.php-fpmコンテナ

Dockerfile

FROM php:7.2-fpm
RUN mv $PHP_INI_DIR/php.ini-development $PHP_INI_DIR/php.ini && \
    sed -i -e "s|;session.save_path = "/tmp"|session.save_path = "/tmp" |" /usr/local/etc/php/php.ini && \
    docker-php-ext-install pdo_mysql && \
    pecl install mailparse-3.0.2  && \
    pecl install xdebug-2.6.1 && \
    docker-php-ext-enable mailparse xdebug

COPY ./xdebug.ini $PHP_INI_DIR/conf.d/

php-fpmのインストールを行います。
ついでにメールパーサーのmailparseとxdebugもインストールしておきます。

3.confファイル

docker.conf

UseCanonicalName Off
EnableSendfile off

<VirtualHost *:80>
    ServerName lvh.me
    ServerAlias *.lvh.me
    VirtualDocumentRoot /var/www/html/%1/public

    <FilesMatch \.php$>
        SetHandler "proxy:fcgi://php:9000"
    </FilesMatch>

    <Directory /var/www/html>
        DirectoryIndex index.php
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    DirectoryIndex index.php index.html
</VirtualHost>

<VirtualHost *:443>
    SSLEngine on
    SSLCertificateFile /etc/ssl/private/server.crt
    SSLCertificateKeyFile /etc/ssl/private/server.key

    ServerName lvh.me
    ServerAlias *.lvh.me
    VirtualDocumentRoot /var/www/html/%1/public

    <FilesMatch \.php$>
        SetHandler "proxy:fcgi://php:9000"
    </FilesMatch>

     <Directory /var/www/html>
        DirectoryIndex index.php
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    DirectoryIndex index.php index.html
</VirtualHost>

FilesMatchでphpコンテナとデフォルトのポート9000を指定してあげます。

また、以下のディレクトリがドキュメントルートになるのですが、
ドキュメントルートの下に複数プロジェクトを置いて開発できるようにしたかったのでVirtualDocumentRootを利用して、プロジェクトのディレクトリ名がドメインになるように設定しています。

docker-lamp/code

lvh.meというドメインを127.0.0.1にDNS登録してくれている人がいるらしいので利用させてもらいました。

[ディレクトリ名].lvh.me

でアクセス可能になります。

4.その他コンテナ

mariaDBやcomposer、phpmyadmin、テストのタスクランナー用のgulpを動かすためのnodeコンテナを入れています。

詳細はリポジトリのREADME.mdを見てください。
temori1919/docker-lamp

5.最後に

イメージが豊富にあってすぐに環境作成ができるdockerは本当に素晴らしいですね。

今はまだローカル開発やツールぐらいでしか使用していませんが、今後はproductionレベルでの使用もしていけるように勉強していければと思います。

それでは皆さまも素敵なdockerライフをお過ごし下さい。