わかる方いましたらお願いします。
docker-composeでローカル環境構築しているのですが
ローカル環境で案件1と2のように複数のDBコンテナで3306で受けることはできませんでしょうか?
案件1と2はディレクトリで分けていてdocker-compose.ymlはそれぞれのディレクトリにあり両ymlファイルに
ports: - :3306:3306
とすると当然portの競合をするので、portsを使う場合3307:3306などと案件ごとにportの管理をしていかなければならないはめになるので、exposeを使えばportの競合はおきませんが、sqlクライアントなどからアクセスできなくなってしまいました。
portの場合、sqlクライアントで127.0.0.1:3006や127.0.0.1:3007で疎通できていましたが
exposeにすると127.0.0.1で疎通ができていないようです。
ちなみに、jwilder/nginx-proxyを使っているのでDBコンテナに名前解決(バーチャルドメイン)指定して、
local.db.anken1.jp:80やlocal.db.anken1.jp:3306としても疎通できません。
SPA開発のdocker構成例ですが一部挙げます。
anken1: build: ./containers/anken1 container_name: "anken1" networks: - container-link environment: - TZ=Asia/Tokyo - VIRTUAL_HOST=local.anken1.jp - LETSENCRYPT_HOST=local.anken1.jp - CERT_NAME=default - NUXT_HOST=0.0.0.0 expose: - 3000 volumes: - ./../services/anken1:/var/www/html - ./config/root/anken1/.bashrc:/root/.bashrc - ./config/root/.vimrc:/root/.vimrc working_dir: /var/www/html command: bash -c "yarn dev" anken1-api: build: ./containers/anken1-api container_name: "anken1-api" networks: - container-link environment: - TZ=Asia/Tokyo - VIRTUAL_HOST=local.api.anken1.jp - LETSENCRYPT_HOST=local.api.anken1.jp - CERT_NAME=default expose: - 80 volumes: - ./../services/anken1-api:/var/www/html - ./config/root/anken1-api/.bashrc:/root/.bashrc - ./config/root/.vimrc:/root/.vimrc working_dir: /var/www/html anken1-db: build: ./containers/anken1-db container_name: "anken1-db" networks: - container-link expose: - 3306 environment: - TZ=Asia/Tokyo - MYSQL_ROOT_PASSWORD=root - VIRTUAL_HOST=local.db.anken1.jp - LETSENCRYPT_HOST=local.db.anken1.jp - CERT_NAME=default volumes: - ./containers/anken1-db/docker-entrypoint-initdb.d/initial.sql:/docker-entrypoint-initdb.d/initial.sql - mysql:/var/lib/mysql - ./config/root/.bashrc:/root/.bashrc - ./config/root/.vimrc:/root/.vimrc
VIRTUAL_HOSTとLETSENCRYPT_HOSTはjwilder/nginx-proxyと連動していて、ホストPCの/etc/hostsにバーチャルドメインを記述して127.0.0.1お紐づけておけばあとは勝手に、jwilder/nginx-proxyを経由して対象のコンテナにproxyしてくれるものです。
フロントとAPIの方は問題なく疎通しています。
ブラウザでnuxt.jsの方も描画されて動いています。
なにが原因なのかと思ってnginx-proxyに入ってnginxの設定を見てみました。
% docker exec -it nginx-proxy bash [nginx-proxy][root@a7435562c65b:0 app]# cat /etc/nginx/conf.d/default.conf
# local.anken1.jp upstream local.anken1.jp { ## Can be connected with "container_network" network # anken1 server 172.18.0.7:3000; } server { server_name local.anken1.jp; listen 80 ; access_log /var/log/nginx/access.log vhost; # Do not HTTPS redirect Let'sEncrypt ACME challenge location ^~ /.well-known/acme-challenge/ { auth_basic off; auth_request off; allow all; root /usr/share/nginx/html; try_files $uri =404; break; } location / { return 301 https://$host$request_uri; } } server { server_name local.anken1.jp; listen 443 ssl http2 ; access_log /var/log/nginx/access.log vhost; ssl_session_timeout 5m; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_certificate /etc/nginx/certs/default.crt; ssl_certificate_key /etc/nginx/certs/default.key; add_header Strict-Transport-Security "max-age=31536000" always; include /etc/nginx/vhost.d/default; location / { proxy_pass http://local.anken1.jp; } }
最終的に、upstreamで3000に転送かけているのでanken1で3000でexposeしているnuxtにアクセスできているのか、ふむふむ。
# local.db.anken1.jp upstream local.db.anken1.jp { ## Can be connected with "container_network" network # anken1-db server 172.18.0.5:80; } server { server_name local.db.anken1.jp; listen 80 ; access_log /var/log/nginx/access.log vhost; # Do not HTTPS redirect Let'sEncrypt ACME challenge location ^~ /.well-known/acme-challenge/ { auth_basic off; auth_request off; allow all; root /usr/share/nginx/html; try_files $uri =404; break; } location / { return 301 https://$host$request_uri; } } server { server_name local.db.anken1.jp; listen 443 ssl http2 ; access_log /var/log/nginx/access.log vhost; ssl_session_timeout 5m; ssl_session_cache shared:SSL:50m; ssl_session_tickets off; ssl_certificate /etc/nginx/certs/default.crt; ssl_certificate_key /etc/nginx/certs/default.key; add_header Strict-Transport-Security "max-age=31536000" always; include /etc/nginx/vhost.d/default; location / { proxy_pass http://local.db.anken1.jp; } }
dbの名前解決の方は、3306でexposeしてるはずなのに80でproxyされている...
nginxの設定ファイルはVIRTUAL_HOSTとLETSENCRYPT_HOSTがあるサービスからproxyが何に設定されているかなど読み取って自動生成されるので、ここのupstreamの172.18.0.5:80;を172.18.0.5:3306;にかえたいところだけど動作がどうなるかよく分からないので、anken1-dbのyamファイルでexposeを80にして試してみました。
そうすればupstreamの172.18.0.5:80;に対して、待ち受けているportが80で辻褄はあるはずなのでこれで疎通確認するも疎通ができない状態です。
anken1の方は、3000でexposeしているのに、local.anken1.jp:3000じゃなくてlocal.anken1.jpでアクセスできるので
同じ考え方でanken1-dbの方も、3306でexposeしたら
upstream local.db.anken1.jp { ## Can be connected with "container_network" network # anken1-db server 172.18.0.5:3306; }
になるんじゃないか?と思いましたが何故か
upstream local.db.anken1.jp { ## Can be connected with "container_network" network # anken1-db server 172.18.0.5:80; }
になっているようです。
私の知見では今ある解決法としては以下の2つです。
- portを分けて管理する
- anken1db-containerやanken2db-containerなどと案件毎にDBを持たずに、ローカル開発環境としてはcommom.db-containerなどとして全ての案件のDBを一元化するような運用にする
どっちも逃げ案になるので、やはり複数のDBコンテナを同時に立てながらも3306で受けるようにしたいです...
どう解決するのが良いでしょうか...
あなたの回答
tips
プレビュー