この記事は
- ローカル環境で開発したNext.jsとGoによるWebアプリをDockerコンテナ上で動作するように移植する方法
- Docker-composeを用いた際のnginxのリバースプロキシの方法
について述べる
あらすじ
以前,個人開発で作成したNext.jsとGoで書いたバックエンドの組み合わせで動作するWebアプリ(ファイルアップローダー)を,実運用するにあたって,Dockerコンテナに移植して,Docker-composeで一発動作するようにしようと思い立った.なので,ゴニョゴニョやったことをまとめる.
前提
-
ファイルアップローダーはGithubにあるので,それをクローンしてきて勝手にセッティングしてほしい
-
フロント側から,バックへfetchする動作があるが,それも1つのドメインで統一して処理できるようにしたい.(Cloudflare tunnnelを使いたい)
- ということで,nginxのリバプロでなんとかする
やったこと
まずそれぞれについてDockerfileを作成した.
作ったDockerFile
フロント側(Next.js)
imageは,node.jsの公式イメージを使用した.まず,githubからリポジトリをクローンしてきて,next.jsのルートディレクトリにWORKDIR
を設定する.
その後,環境変数を設定するために,.env.local
をルートディレクトリ直下にコピーする.そして,npm install
で依存関係をインストールし,npm run build
でビルドしておく.ちなみに,.env.localは実行のたびに読み込まれる.
(参考: https://zenn.dev/aktriver/articles/2022-04-nextjs-env )
下記に,Dockerfileの例を示す.EXPOSEはnextで指定されるアクセスポートを設定しておく.
FROM node:23.6
WORKDIR /node
EXPOSE 3000
RUN git clone https://github.com/syou551/dirShareApp.git
WORKDIR /node/dirShareApp/front/dir-share
COPY ./.env.local .
RUN npm install\
&& npm run build
バック側(Go)
imageは,Goの公式のものを用いた.フロント側と同様にリポジトリをクローンして,バック側のディレクトリに移動する.その後,依存モジュールをgo mod tidy
でインストールし,その後ビルドする.
ちなみに,go.modがないと怒られてビルドできないので,開発段階でgo mod init
を忘れないようにしよう.(参考: https://qiita.com/TakanoriVega/items/6d7210147c289b45298a )
FROM golang:1.23
WORKDIR /go/src
EXPOSE 80
RUN git clone https://github.com/syou551/dirShareApp.git
WORKDIR /go/src/dirShareApp/back
RUN go mod tidy\
&& go build main.go handler.go
nginx
imageはnginxの公式のものを使った.Dockerfileは単に設定ファイルをコピーしているだけである.
FROM nginx:latest
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
本題は,設定ファイルである.リバースプロキシのための基本的な設定は同様であるが,今回はdocker-composeで動かすことを念頭において設定をする.
Dockerでは,docker composeをすると,Networkを明示的に記述しない限りは,それぞれは検出可能となり,それぞれのコンテナへサービス名を指定することでアクセスできるようになる.
- Ex.) serviceがfrontなら,(プロトコル)://front:(ポート)のような形でアクセス可能
(参考: https://docs.docker.jp/compose/networking.html )
これを使って,nginxのproxy_pass
をサービス名に合わせて設定すれば良い.
また,今回は,外部へ向けて公開するポートは1つに絞りたいため,locationによってフロント側かバック側かを振り分けるようにする.以下の例では,/dir/
以下のパスへのリクエストは,バックへ流すように設定している.ただし,バック側では/dir/
を含むリクエストは設定しておらず,リバプロのために勝手につけたパスであるため,取り除いてそれ以降のパスを流すようにしたい.
このためには,proxy_pass
の最後に/
をつけることで,/dir/hoge/huga
へのリクエストは,{proxy_passで設定した宛先}/hoge/huga
へ飛ばすことができる.ちなみに,/
をつけない場合は,トリミングされずそのまま渡される.これいつもどっちかわからなくなるので困る.
(参考: https://qiita.com/mkuwan/items/dce68409aaf16142a438 )
server{
listen 80;
server_name app;
location /dir/ {
proxy_pass http://back/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://front:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
作ったdocker-compose.yaml
次に,こいつらをdocker compose up
で一括処理できるように,yamlを書いていく.ちなみに, 一応説明すると,docker-compose.yamlは,複数のコンテナをこんなふうに動かしてくださいと指示するための指示書である.
まず,今回は各コンテナに対してすでにDockerfileを作成したので,build
でDockerfileを配置しているディレクトリ(context)とそのファイル名を指定する.
今回のディレクトリ構成は以下のような形である.
FileUploader
|- docker-compose.yaml
|- front
| |- Dockerfile
| |- .env.local
|
|- back
| |- Dockerfile
|
|- nginx
|- Dockerfile
|- nginx.conf
なので,context
とdockerfile
は以下のように設定すれば良い.
サービス名:
build:
context: ./front
dockerfile: Dockerfile
その後,フロント側とバック側に関しては,起動するために,ルートディレクトリにworking_dir
を設定する.そして,command
で起動コマンドを入力すれば良い.なお,bashなどを使いたい時は,command: bash -c "./main"
のように指定する.
(参考: https://qiita.com/ntrlmt/items/cce919c14e4dff07e7ee )
また,nginxに関しては,フロントとバックが起動しているかどうかを確認してから起動するように,depends_on
を指定しておく.
また,外部に開くポートに関しては,nginxだけを見せれば良いでの,ホスト側の任意のポートとnginxがListenしているポートをマッピングさせておく.
nginx:
ports:
- "8080:80"
以上の項目を書き込んだyamlの例を以下に示す.
services:
front:
build:
context: ./front
dockerfile: Dockerfile
working_dir: /node/dirShareApp/front/dir-share
command: npm run start
back:
build:
context: ./back
dockerfile: Dockerfile
working_dir: /go/src/dirShareApp/back
command: bash -c "./main"
nginx:
build:
context: ./nginx
dockerfile: Dockerfile
depends_on:
- front
- back
ports:
- "8080:80"
動作確認
docker compose up
をすると,自動でコンテナがビルドされ,アプリも起動.今回の設定では,localhost:8080
にアクセスすれば,next.jsのアプリ画面が開き,操作すると無事バックにもリクエストが通っているのが確認できました.ちなみに,設定ファイルはgithubで公開しています.
まとめ
Docker composeを使えば,1コマンドで一連のアプリを自動で起動させることができるようになりました!