docker-composeを使って一瞬でLAMP+SSL環境を作る方法

2021年1月1日

この記事を読むと得られる情報

1コマンドで

  • Nginx(SSL化用リバースプロキシ)
  • MariaDB
  • CentOS7
    • Apache
    • php

のコンテナが下記の簡略図で立ち上がり、gitかなにかでwebアプリコンテンツをDocumentRootに置けば、すぐに使えるようになる。

システム構成図
簡略図

本稿のレベルとしては
「dockerとdocker-composeが何なのかはなんとなく知ってるけど、あんまり使ったことない人」向けです。

それぞれの基本知識としては下記を斜め読みすれば十分だと思います。

俺はさっさと環境ができれば、どうだっていいんじゃーって人は
「デプロイ」までで実施できます。
各機能の詳細や、詳細な関係が気になる人は最後まで読んで見てください!

環境用意

CentOS Linux release 7.4.1708 (Core)

下記で示すDockerとdocker-composeのバージョンさえ合ってればなんでもいいです。
macOS High Sierra 10.13.4でも動作確認済みですが、本記事はCentOSでの実施手順です。

Docker version 18.03.0-ce, build 0520e24

# dockerインストール手順

# dockerリポジトリを追加
sudo wget https://download.docker.com/linux/centos/docker-ce.repo
# インストール
sudo yum install docker-ce
# dockerの起動
sudo systemctl start docker
# docekrの自動起動設定
sudo systemctl enable docker
# ユーザーでdockerが使えるようにグループ設定
sudo groupadd docker
sudo gpasswd -a $USER docker
# docker再起動
sudo systemctl restart docker
# バージョン確認
docker -v
> Docker version 18.03.0-ce, build 0520e24

docker-compose version 1.20.1, build 5d8c71b 以上

# docker-composeインストール手順

# 資材ダウンロード
sudo curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 実行権限を付与
sudo chmod +x /usr/local/bin/docker-compose
# バージョン確認
docker-compose -v
> docker-compose version 1.20.1, build 5d8c71b

【任意】DDNSへの登録(ドメイン)

SSL化に必要なドメインを取得します。
無料かつ、IPの変化に対応できるDDNSとしておすすめはMyDNSです。
任意のドメインを入手しておいてください。
後述しますが、hogehoge.mydns.jpなど人気なドメインは避けたほうが良いです。

構築

カレントディレクトリは任意ですが、ユーザーディレクトリがいいと思います。
カレントディレクトリに下記のようなファイルを構築します。

# ディレクトリ構成
.
├── db
│   ├── Dockerfile
│   ├── init.d/
│   ├── init.s/
│   ├── my.cnf
│   └── vol/
├── docker-compose.yml
└── web
    ├── Dockerfile
    ├── conf
    │   └── httpd.conf
    ├── html/
    └── php.ini

docker-compose.yml

docker-compose.ymlはyml形式で書かれたファイルで、名前の通りdocker-composeの設定ファイルです。
ここで各種dockerコンテナ(今回はCentOSとNginx、MariaDB)の設定を記述します。

# docker-composeのバージョン宣言
version: '2'
services:
  # MariaDBの設定
  maria:
    # Dockerfileの場所
    build: ./db
    # コンテナ名の定義
    container_name: maria
    # 環境変数の設定 docker runの-eオプションに対応
    environment:
      # MariaDBのrootユーザーのパスワード
      MYSQL_ROOT_PASSWORD: hogehoge
    # データ保存場所指定
    volumes:
      # データベースの永続化を定義
      - ./db/vol:/var/lib/mysql
      # データベースの初期化スクリプト置き場
      - ./db/init.s:/docker-entrypoint-initdb.d
      # データベースの初期データ置き場
      - ./db/init.d:/var/lib/ram
    # 所属するネットワークとIPを指定
    networks:
      br0:
        ipv4_address: 192.168.200.2
  # httpdの設定
  httpd:
    # Dockerfuleの場所
    build: ./web
    # コンテナ名の定義
    container_name: httpd
    # データの保存場所
    volumes:
      # DocumentRootのホスト側とのリンク
      - ./web/html:/var/www/html
    # 直前の起動コンテナの設定
    depends_on:
      - maria
    # 所属するネットワークとIPを指定
    networks:
      br0:
        ipv4_address: 192.168.200.3
  #リバースプロキシの設定
  https-portal:
    # イメージの定義
    image: steveltn/https-portal:1
    # ポートフォワーディング
    ports:
      - '80:80'
      - '443:443'
    # NATの設定
    extra_hosts:
      - '"DDNSで取得したDNS":127.0.0.1'
    # コンテナ同士の接続
    links:
      - httpd
    # 環境変数の設定
    environment:
      # 本番用
      DOMAINS: '"DDNSで取得したDNS" -> http://httpd'
      STAGE: 'production'
    # 所属するネットワークとIPを指定
    networks:
      br0:
        ipv4_address: 192.168.200.4
# 新規ブリッチを定義
networks:
  br0:
    driver: bridge
    ipam:
      config:
      - subnet: 192.168.200.0/24
        gateway: 192.168.200.1

db/Dockerfile

# ベースイメージを定義
FROM mariadb:5.5
# my.cnfを定義
COPY ./my.cnf /etc/

web/Dockerfile

# 元とするイメージ名
FROM centos:latest
# 各種ミドルウェア
RUN yum install -y php | true 
RUN yum install -y php-mysql | true
RUN yum install -y net-tools | true
RUN yum update -y
# 各種設定ファイルのコピー
COPY ./conf/httpd.conf /etc/httpd/conf/
COPY ./php.ini /etc/
# ポートの解放
EXPOSE 80
# httpdの起動
CMD /usr/sbin/httpd -DFOREGROUND

各種設定ファイル

  • db/my.cnf
    • 普段のmariaDBで使用してるものを用意
  • web/conf/httpd.conf & web/php.ini
    • こちらも普段使用しているapacheの設定ファイルと、php.iniファイルを用意
  • web/html/*
    • デプロイしたいwebアプリの資材をここに入れてください

デプロイ

さて、いよいよコンテナの立ち上げです。
docker-compose.ymlがあるディレクトリまで移り

# コンテナの立ち上げ
docker-compose up -d --build
# 動作の確認
docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                                      NAMES
60c73d6a06f2        steveltn/https-portal:1   "/init"                  8 hours ago         Up 8 hours          0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   dockerlamp_https-portal_1
7af11daaa0f9        dockerlamp_httpd          "/bin/sh -c '/usr/sb…"   8 hours ago         Up 8 hours          80/tcp                                     httpd
ac12e8c7ce8c        dockerlamp_maria          "docker-entrypoint.s…"   8 hours ago         Up 8 hours          3306/tcp                                   maria

となれば、完了!!
取得したドメイン名でアクセスして、アプリの動作を確認してください。

Q&A

  • コンテナが正常に起動しない
    • $ docker-compose logsで各種コンテナの状況が確認できます
  • 証明書の発行時にドメイン上限に引っかかって発行できない

詳細

ネットワーク関係

序盤に簡単なネットワーク構成を書きましたが実際にはこんな感じ

ネットワーク構成図
ネットワーク構成図

NginxとmariaDBとCentOSベースのコンテナの3つが起動してます。
NginxとmariaDBは設定内容が簡単なことから分かる通り、そのまま使用しています。
CentOSのコンテナのみweb/Dockerfileでyumを使った初期インストールでApacheやphpを導入しています。
(そこを変更すればpythonだって環境を作ることが可能です)

コンテナ同士はdocker-compose.ymlの最後に記したネットワーク内での相互通信を行っています。

インターネット(外部)との通信はdocker-compose.ymlのNginxの部分で設定した部分(port) で定義しており、
ローカルマシンの対応するポートとポートフォワーディングで通信を行っています。
また今回はlet’s encryptではなくオレオレ証明書でアクセスでアクセスすることも可能です。
既存環境に手を加えずにサクッとHTTPS化する (NAT配下でもok)

さらに、docker-compose.ymlからhttps-portalの設定を全削除して、webでポートフォワーディングを設定すればDDNSも不要になります。

オプションディレクトリの説明

3章で空のディレクトリを複数作りましたが、それぞれ役割があります。

db/init.s

docker-compose.ymlの./db/init.s:/docker-entrypoint-initdb.dにも書いてありますが
init.sに入れたファイルはmariaのコンテナのdocker-entrypoint-initdb.dにコピーされます。
コンテナ側のdocker-entrypoint-initdb.dというディレクトリは特殊で
ここに入れられたshファイルや、sqlファイルはコンテナ立ち上げ時にアスキーコード順に実行されます。
なので、ここにはDBの初期データを流し込むスクリプトファイルなどを入れます。

db/init.d

docker-compose.ymlの./db/init.d:/var/lib/ramにも書いてありますが
init.dに入れたファイルはmariaのコンテナの/var/lib/ramにコピーされます。
ここは単純にコピーされるだけなので
init.sで実施されるスクリプトが読みに来るDBのダンプデータなどを入れます。

5-2-3. db/vol

ここはDBのデータそのものが入ります。
テーブルスキームや、カラムの値などが入っています。
ここのデータをコピーしておけばバックアップとして使えます。