WEBアプリテンプレート(django+javascript)

code
code
nginx
nginx
Dockerfile
Dockerfile
docker-compose.yml
docker-compose.yml
conf.d
conf.d
uwsgi_params
uwsgi_params
project.conf
project.conf
project.conf
project.conf
/
/
[PROJECT]
[PROJECT]
docker
マウントポイント
docker…
サイト構築
ポイント
サイト構築 ポイント
プロジェクト構成
プロジェクト構成
Text is not SVG – cannot display
# 通常起動
$docker-compose up -d
# 再構築
CLEARSITE=1 docker-compose up -d
テンプレート表示状態

WEBアプリの勉強を始めた所、djangoを用いて同じ構成のサイトを何度も構築するのが面倒でテンプレートを作ることにした。しかしコレばっかりに夢中で肝心の勉強の方がおろそかになってきているのは、いつものお約束。

テンプレート構成

  • docker image 仕様(Dockerfile)
    • debianベースのpythonスリムイメージをベースとする
    • pythonライブラリインストールステージ:dbアクセス用ライブラリの為に一時的に開発ツール一式をインストール(後にスリム化処理)
    • nodejsは一旦aptパッケージインストールした後、npmで最新のバージョンをインストール
    • npmでtypescript、sass、bootstrapをインストール
    • その他チョットしたツール:gitやwget、アプリ実行用ユーザー(user)の作成とsudo権限設定
    • 実行コマンドは/code/startupシェルスクリプト:イメージにはダミーのシェルスクリプトを格納しているが、実際はサイト構築テンプレートとwusgi起動を含むシェルスクリプトを/code/startupとして作成しマウントして実行(後述)。
  • 起動:docker-compose構成
    • djangoは/codeをマウントしてサービスを実行
    • 環境変数CLEARSITE=1とすることでサイトを削除してテンプレートで再構築する(危険コマンド)
    • 構築用のstartupスクリプトが長いため、djangoサービスが始める前にnginxからのサービス要求がありロックすることがあったので、ヘルスチェックを行うようにしている(uwsgiのプロセスチェック)。
  • startupスクリプト(テンプレート構築&サービス起動)
    • 環境変数でサイト名アプリ名を定義し、サイト名のディレクトリが存在しない場合、またはCLEARSITEでアプリを削除している場合、テンプレートを用いてアプリケーション雛形を構築する。
    • Django-admin startupprojectでサイトを構築、settings.pyの必要な部分を順次編集。
    • python manage.py startappで最初のアプリケーションを作成(これを用いてシングルページアプリケーションの雛形とする)
    • アプリケーションの設定部分をsettings.pyに追記編集。bootstrapなどのミドルウェアの設定、LOGGING設定、環境変数読み込み設定。
    • ルート用urls.py、フロント側にデフォルト変数を送る機構context_processors.pyの雛形作成
    • アプリケーション定義用urls.py、views.pyの雛形作成、indexページとajax待ち受けの最低限構成、およびテンプレートHTMLのindex.html、base.html雛形作成。
    • python manage.py migrate :sqliteデータベースの初期化、管理者ユーザーの作成
    • スタティック領域の構成
      • bootstrapはnpmのグローバルエリアからローカルコピー(これは最新版に対応するため常に行う)
      • サイト用カスタムscssのテンプレート作成(再構築時)
      • sass常駐コンパイラの起動(上記scssファイルの更新と同時に自動コンパイル)
      • bootstrap関連その他js、およびtinymce設定
      • DOM構築用javascriptモジュールテンプレート(TSソース)設置、およびTypeScript初期化と設定ファイル初期編集(再構築時)
      • tsc常駐コンパイラ起動

テンプレートに凝りすぎてほぼほぼ自由度が下がってしまっている件。前回のDOM構文もTypescriptに移植して使える状態にして用意してます。細かい解説は折りを見て追記します。

FFmpeg on Docker

久々の投稿

dockerイメージでFFmpegをフルコンパイルしてみました。第1の理由は興味本位ですが、あとSVTAV1のライブラリを使用したいのと、tarボールからコンパイル&インストールして通常使用の環境が汚れるのをある程度防ぎたかったというのもあり、実験環境としてのDockerで行うこととした。副次的な効果として、Windows環境やMac環境、ひいてはRaspberryPi環境のどれか空いてるマシンで動画変換作業をさせることが出来る。

Dockerfileの解説

ベースとするイメージはpython:3.10.3-slim-bullseyeでDebianスリムイメージを利用しました。

pythonのビルドと同様に

  1. 現在のaptパッケージを保存(python環境など)
  2. aptで開発環境をドヤ−−−−っとインストール
  3. debianのライブラリにはfdk-aacがパッケージとして存在しないので、sourceforgeからソースコードをダウンロードしてビルド&インストール
  4. 開発環境が一通り完成したところで、SVT-AV1をgithubからcloneしてビルド&インストール
  5. ライブラリが揃ったので、ひとまずldconfigしてから、目的のffmpegをこれもgithubからcloneしてビルド&インストール
  6. このままではDockerイメージサイズが大変なことになっているので、不必要なパッケージを削除します。
  7. apt-markコマンドを使用して、2番以降でインストールしたパッケージをauto-remove対象にします(1番以前のパッケージは対象としない)。
  8. /usr/local 以下にある実行ファイルに関してlddコマンドを使用して関連するダイナミックライブラリをリストアップ、さらにそれらを含むaptパッケージを検索してリストアップしてauto-remove対象外にする。
  9. aptコマンドを使用しauto-removeで不必要なパッケージをゴッソリ削除
  10. イメージのスリム化を行った所でステージを分けて、Python用の必要パッケージをインストールしてffmpeg-pythonなどが利用できるようにする

イメージのスリム化のための仕組みはベースとしたpython:3.10.3-slim-bullseyeを参考に・・・というか殆どパクりで使用しました。1〜9までを一つのRUN文で行うのがミソ。RUN文で分けた方が見やすいけど、ビルドのステージが分かれてしまうのでステージが変わってからパッケージを削除してもイメージサイズが変わらないというの何とも。。

ビルドファイルの開発中などは複数のステージに分かれていた方がデバッグしやすくて良いが、一通り完成したら一つのRUN文にまとめてしまう感じですかね。

wordpressのdocker化と既存データの移植

従来環境ではApache2+MySQLでしたが、dockerへの移植時はwebの情報を参考にnginx+php+fpm+mariadbとしました。DockerHubからwordpress+fpmとmariaDBの公式イメージを使用して構築しました。

version: '3.1'
services:
  db:
    image: mariadb:latest
    container_name: mariadb_wp
    volumes:
      - mariaDb:/var/lib/mysql
      - ./db_backup:/backup
    restart: always
    command: --innodb-read-only-compressed=OFF
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: wpdata
      MYSQL_USER: user
      MYSQL_PASSWORD: password
      TZ: Asia/Tokyo
  php-fpm:
    image: wordpress:5.8-fpm
    container_name: php_wp
    volumes:
      - ./blog:/var/www/html
      - ./conf/upload.ini:/usr/local/etc/php/conf.d/upload.ini
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: webdata
      WORDPRESS_DB_PASSWORD: password
      WORDPRESS_DB_NAME: user
      TZ: Asia/Tokyo
  nginx:
    image: nginx
    container_name: nginx_wp
    depends_on:
      - php-fpm
    environment:
      - VIRTUAL_HOST=blog.marochanet.org
      - TZ=Asia/Tokyo
    volumes:
      - ./blog:/var/www/html
      - ./conf/default.conf:/etc/nginx/conf.d/default.conf
      - ./conf/nginx.conf:/etc/nginx/nginx.conf
    expose:
      - '443'
    restart: always

volumes:
  mariaDb:

networks:
  default:
    external:
      name: shared

最後のsharedネットワークへの参加とnginxホストの環境変数VIRTUAL_HOSTでリバースプロキシで構成する仮想ホスト名でアクセス出来るようになっています。この場合ここではport公開せずにexposeを使用します。

mariaDBはwordpressだけではなくその他django、rainloop、nextcloudでも使用するが、とりあえずこのcomposeプロジェクトで立ち上げておく(他のcomposeからもDBホストmariadb_wpでアクセス出来る)。

nginxホストの設定:nginx.conf と default.confはサンプルのまま

$ cat /conf/nginx.conf
user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$uri - $is_args - args :::'
                      '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    include /etc/nginx/conf.d/*.conf;
}

$ cat /conf/default.conf
server {
    index index.php;
    charset utf-8;
    server_name localhost;
    root /var/www/html;
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    location ~* /wp-config.php {
        deny all;
    }
    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }
    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php-fpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    location ~* .(html|css|js|jpe?g|png|gif|svg|mpg|flv|swf)$ {
        expires max;
        access_log off;
    }
}

このままアクセスすると、言語およびadminのパスワード設定など初期設定が始まる。今回は既存サイトの移植が目的だが、まずはこのまま初期化して素のwordpressがアクセス出来るようにします。そののちwp-contentsを既存サイトのものと置き換えます。この段階では一度ポートを閉じるなどしてアクセス出来ないようにしておく必要があるかも知れません。

$ sudo rm -rf wp-contents
$ sudo cp -rf [old position]/wp-contents .
$ sudo chown -R www-data.www-data wp-contents 

次にデータベースのコピーですが。まずは既存サイトのデータベースをバックアップします。たとえば同じホストのmysqlからバックアップするとして

$ mysql-dump --lock-all-tables -u root -p --databases wpdata > wpdata.sql
Passwrd:

今回はmysqlからmariadbへの移植も兼ねているので、そのままではエラーになるため、キーワードを入替えておく必要がある。

今回の場合ではunicodeの表現方式で

utf8mb4_0900_ai_ci => utf8mb4_unicode_ci

に変換しておく必要があった。

変換の後、コンテナのデータベースにリストアします。メンテナンス用にdbサービスにマウントしているdb_backupにコピーしてから

$ docker-compose exec db /bin/bash
db$ mariadb -u root -p
mariadb> drop database wpdata
mariadb> quit
db$ mariadb -u root -p < /backup/wpdata.sql

すでに作成済のデータベースwpdataを一旦削除してから改めてバックアップデータをリストア

これにて無事移植が完了しました。

ここまで簡単な流れにまとまったけど、これでも結構失敗を繰り返したり、、あーでもないこーでもないと試した結果だったりします。その紆余曲折をまとめられれば良いのだが、やってるときは悩みながら突っ走ってしまうので、過程があまり残らないことが間々あるw

dockerリバースプロキシ環境

前記事で書いたように従来のApache仮想ホストと同じことをdockerブリッジネットワークで構成するためには、リクエストホスト名によって接続コンテナを切り替える機能が必要とのこと。しっかり勉強すれば自力でも出来るかも知れないが、先人の作り上げた構成をお手軽に実現出来るのがdockerの良いところということで、ネット検索でも評判の良いjwilder/nginx-proxyを使用することにしました。

version: '3'
services:
  nginx_root:
    build: ./rootimg
    image: jwilder/nginx-proxy:certbot
    container_name: nginx_root_container
    hostname: nginx_host
    depends_on:
      - http_default
    privileged: true
    environment:
      - DEFAULT_HOST=base.marochanet.org
      - TZ=Asia/Tokyo
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
    networks:
      default:
        ipv4_address: 192.168.29.2
    ports:
      - "80:80"
      - "443:443"
    restart: always
  http_default:
    container_name: http_default_container
    image: nginx
    hostname: http_default_host
    expose:
      - "80"
    environment:
      - VIRTUAL_HOST=base.marochanet.org
      - TZ=Asia/Tokyo
    volumes:
      - ./html:/usr/share/nginx/html
    restart: always

networks:
  default:
    driver: bridge
    name: shared
    ipam:
      config:
        - subnet: 192.168.xx.0/24
          gateway: 192.168.xx.1
          ip_range: 192.168.xx.16/28

nginx_rootというサービスがjwilder/nginx-proxyを使用したリバースプロキシコンテナです。build:でイメージを作り直していますが、Letsencryptの証明書を取得/更新するためにcertbotをインストールしているだけです。

  • rootimg/Dockerfile
FROM jwilder/nginx-proxy

ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update \
    && apt-get install --yes --no-install-recommends \
      certbot \
    && rm -rf /var/lib/apt/lists/*

2個目のサービスhttp_defaultはとりあえずのWEBサーバー。テスト用にHTML返すだけなので特別なことはしていませんが、これだけでOKです。キモはenvironment節の環境変数として記されたVIRTUAL_HOSTで、ここに設定したURL向けのリクエストがこのコンテナに向けられるようにリバースプロキシが上手い具合に設定してくれます。

プロキシサービスのコンテナにある環境変数DEFAULT_HOSTはそのまんまの意味で、行き先の見つからない宛先(IPアドレス直とか)の場合の飛び先で、この場合宛先がhttp_defaultサービスと同じになっているので、迷い込んで来た人?IPアドレスで飛んできたスキャンな人へのメッセージページ/エラーページにすると良いかもしれません。

一番最後のnetworks:ではブリッジネットワークの設定をしています。name:節の shared がネットワーク名になります。サブネット、ゲートウェイが設定出来、さらに ip_rangeは、よく理解出来てませんが、固定IPを割り当てる範囲を決めているようでした。固定IPは 1~15で、DHCP的なアドレス割当ては16以降になっているようです。

基本的にはこの共通ネットワークに入ってさえいれば同じdocker-composeで作成していないサービスでもリバースプロキシの傘下に入ることが出来ます。別プロジェクトのdocker-composeでは、外部参照のネットワークとしてsharedを定義しておきます。

networks:
  default:
    external:
      name: shared

当サイトの他のサービス(djangoサイト、wordpress、rainloop WEBメール、nextcloud)は全てこの方法でリバースプロキシ傘下に入っています。

certbotも入れたので、次はletsencryptでの認証関連の設定となりますが、今回は割愛しています。jwilder/nginx-proxyではお手軽な方法が用意されているので、letsencrypt用の起動スクリプトも含めて次回のメモ記事で紹介します。

docker環境も整って勉強や実験も一段落してきたので、そろそろブログネタの方向性も(趣味的な方向へ)変えていきたいなと思うのですが、コロナとか自粛モードでなかなかネタ集めが出来ないですねー(言い訳
・・・・まぁこのへんのネタもじゅーーーぶんに趣味的ではあるけど。

docker対応ufw(iptabels)設定の件

ここでdockerについての解説をするのはおこがましいので、下記に覚え書きリンクを貼付ける

ローカルLAN環境でWEBサーバーを運用するだけなら良いが、当サイトにdockerを導入するに当たって一番の懸念事項がファイアウォールとの相性問題があった。

当サイトと同じUbuntu20.04LTSで下記のようなファイアウォール設定であったとして

xxxx@user$ sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

dockerコンテナで8080ポートでwebサイトを立ち上げると、ファイアウォールをするりと抜けて外部に公開できてしまう(下記テキトウdocker-compose.yml)

web:
  image: nginx
  volumes:
   - ./templates:/etc/nginx/templates
  ports:
   - "8080:80"
  environment:
   - NGINX_HOST=foobar.com
   - NGINX_PORT=80

当サイトではufwファイアウォールの運用で特定IPアドレスからのアクセスを遮断している(メールサーバへの不正アクセスやwordpressへの不正ログイン試行を手動・自動で監視して遮断対象アドレスをリストアップ)。

ufwコマンドで設定するポートアクセス許可よりも前で設定するために、/etc/ufw/before.rules に記載のあるチェインufw-before-inputにログ出力と遮断コマンドを追加している。

# blacklist-ipset-S ここにブロック対象のアドレスを追加
-A ufw-before-input -s xxx.xxx.xxx.xxx -j auto-blocklist
# blacklist-ipset-S

# タグをつけたログを残してドロップさせるチェイン
# ファイルの先頭の*filter節に追加する必要あり?
-A auto-blocklist -j LOG --log-prefix "[BLOCKLIST]"
-A auto-blocklist -j DROP

こうすることでufw起動時にiptableの遮断リストが設定される。

しかし、上記のdockerコンテナはこの設定も効かず、遮断対象アドレスも通過してしまう。

そこで、まずdockerコンテナが何故ufwの設定を無視できるのかを調べてみる。(iptableコマンド)

user@server:~$ sudo iptables -nvL
Chain INPUT (policy DROP 2979 packets, 152K bytes)
 pkts bytes target     prot opt in     out     source               destination
3687K 3750M ufw-before-logging-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
3687K 3750M ufw-before-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
83453 4149K ufw-after-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
77337 3836K ufw-after-logging-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
77337 3836K ufw-reject-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0
77337 3836K ufw-track-input  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
4406K 5775M DOCKER-USER  all  --  *      *       0.0.0.0/0            0.0.0.0/0
4406K 5775M DOCKER-ISOLATION-STAGE-1  all  --  *      *       0.0.0.0/0            0.0.0.0/0
3634K 4639M ACCEPT     all  --  *      br-a52db8fb2804  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
80854 4814K DOCKER     all  --  *      br-a52db8fb2804  0.0.0.0/0            0.0.0.0/0
 675K 1102M ACCEPT     all  --  br-a52db8fb2804 !br-a52db8fb2804  0.0.0.0/0            0.0.0.0/0
70296 4218K ACCEPT     all  --  br-a52db8fb2804 br-a52db8fb2804  0.0.0.0/0            0.0.0.0/0
71973  318M ACCEPT     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 DOCKER     all  --  *      docker0  0.0.0.0/0            0.0.0.0/0
54110 3031K ACCEPT     all  --  docker0 !docker0  0.0.0.0/0            0.0.0.0/0
    0     0 ACCEPT     all  --  docker0 docker0  0.0.0.0/0            0.0.0.0/0
    0     0 ufw-before-logging-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ufw-before-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ufw-after-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ufw-after-logging-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ufw-reject-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0
    0     0 ufw-track-forward  all  --  *      *       0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 4 packets, 196 bytes)
 pkts bytes target     prot opt in     out     source               destination
3574K 2258M ufw-before-logging-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
3574K 2258M ufw-before-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
27893 2070K ufw-after-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
27893 2070K ufw-after-logging-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
27893 2070K ufw-reject-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0
27893 2070K ufw-track-output  all  --  *      *       0.0.0.0/0            0.0.0.0/0

この辺りもこのために改めて勉強したため、理解不足かも知れないが、、、

普通にufwで設定するファイアウォールはINPUTチェインが主で、5行目のufw-before-inputのチェインから繋がっている(当サイトのアクセス遮断リストもここに繋げている)。それに対してdockerのファイアウォールはFORWARDチェインであり、16,20行目のDOCKERチェインでコンテナで設定したポートの待ち受けを実現している。それはufwのFORWARD設定よりも優先しているので、アクセス制限はそれよりも前で行う必要がある。ここでアレ?と思うのがDOCKERチェインよりも前にあるDOCKER-USERチェイン。このチェインの中身は空白で何もせずに帰ってくる仕組み。

ならば、ここに遮断リストを追加してやれば良いんじゃね?という感じで、

$ sudo iptables -A DOCKER-USER -s xxx.xxx.xxx.xxx -j DROP

としてみたら、無事遮断していることを確認(とりあえずスマホのIPアドレスを遮断してみて確認)。

実は英文の方のdocker docsにはそれっぽいことが書いてあった。。

次に問題はこのリストを起動時に読み込ませるにはだけど、これは何のことはなくufwの助けが借りられることが分かった。先の遮断リストをログ出力しつつDROPするチェインを追加した要領でDOCKER-USERチェインも/etc/ufw/before.rulesに記載してしまおうという思いつきで実験、、上手く動作したので下記に示します。

$ sudo cat /etc/ufw/before.rules
# Don't delete these required lines, otherwise there will be errors
# added for docker access limits. 21/08/17 by mamiyan
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
:DOCKER-USER - [0:0]           # <---- これ追加
:auto-blocklist - [0:0]        # <---- ログ出力&DROP処理用チェイン
:docker-blocklist - [0:0]      # <---- 同上
# End required lines

・・・・・
# for blocklist custon chain 追加チェイン
-A auto-blocklist -j LOG --log-prefix "[DROPLIST]"
-A auto-blocklist -j DROP

# for docker custom chain 追加チェイン
-A docker-blocklist -j LOG --log-prefix "[DROPDOCKER]"
-A docker-blocklist -j DROP

# blacklist-ipset-S ここから
-A ufw-before-input -s xxx.xxx.xxx.xxx -j auto-blocklist
-A DOCKER-USER -s xxx.xxx.xxx.xxx -j docker-blocklist
# blacklist-ipset-E ここまでにリスト追記

24行25行のように二つのチェイン向けに遮断アドレスリストを追記して、$ sudo ufw reload でdocker向けのファイアウォールが設定されます。その他のアクセス制限もこの/etc/ufw/before.rules の DOCKER-USERチェインに記載しておけば良いと思います。

この辺りは、ufwを少し触れる程度の知識からiptableの仕組みとチェインを触れる程度までじっくり勉強が出来て良かったと思います。またここでCentOSとかのRHL系でfirewalldとかになると変ってくるのだろうか。そもそもあちら側は相性問題は無いのかな。

docker環境への移行

約一ヶ月ぶりの記事になりますが、夏休みということで。

この夏休みは、雨続きやら新型コロナの蔓延防止やら緊急事態やらの巣ごもりで、夏バテと闘いながら、従来から引続きpython(django)、javascript(Three.js)勉強行いながら、前回の記事でチラッと書いたdockerの勉強・実装実験を行っておりました。もともろvmwareやら仮想環境に興味があったので、比較的敷居が低かった感じで、いろいろ試しているウチに勢い余って、当サイトのWEB環境もApache2の仮想ホスト環境から、dockerコンテナのブリッジネットワーク構成に移行させてしまったというお話。さらにはメールサーバーもdockerコンテナ化・・・8月中に一通り移行を終えたところで一息ついている感じです。

とっかかりは楽しくて次々とdocker化が進んでいったが、やっぱり全く同じ環境を再現しようとすると色々と問題が出てきたり、ネット調査だけでは答えの出ない問題に突き当たったりとネタだけは貯えたので、覚え書きレベルですが追々と記事にして置こうかと思います。

つい今の今も、この記事を書こうとwordpress(これもdockerコンテナ化済み)の記事編集をしていたところ、メディアファイルがアップロード出来ない問題が発生(移行時に試していないのがいけない・・・)。半日がかりの原因究明でしたが、結局はアップロードパスの修正忘れという単純なポカミス。。まぁdockerという新しい環境への移行なので、まずそちら方面を疑ってしまい、思わぬ深みにはまってしまうというよくある罠でした。

今回の移行ですが、従来構成を下記に示す。普通のubuntuのままなのでapache単独サーバーでvhost.confの設定で仮想ホストを構成していた。

従来構成

同様の環境をdockerリバースプロキシ環境に移行した構成を下記に示します。

移行後のdocker構成

dockerブリッジネットワークでほぼ全てのサービスをコンテナ化してリバースプロキシサーバにて80番ポートと443番ポートを受けて文字通りの仮想ホスト構成としている。メールサーバーは受信のために25番ポートを空けているが、こちらは図のように直接外に向けてポートを空けてしまうと、ホスト内のサービスメール(cronやlogwatchなど)が動作しなくなってしまうので、実際はホスト側でもpostfixを動作させホスト内メールの面倒を見ながら外部から来たメールはコンテナのメールサーバーに転送する仕組みとしている。

一ヶ月の試行錯誤の結果ほぼ従来通りの動作を確認できたが、なんか妙に重いかも知れない。。。

久々のブログ記事でいきなりファイルアップロード不可とか、メッチャ焦りました。新環境では十分なテストが必要ですね。メールサーバーのdocker化もテキトウに確認して運用始めては→問題発覚→環境戻し→デバッグやり直し-の繰返しでした。たいていはショウモナイポカミスなんですが、そういうのに限って見つけるのに半日から1日作業となるのが定期。