はじめに
ようやくDockerを学び始めたので自分の理解をまとめておく。
前回 => https://qiita.com/theFirstPenguin/items/58e6bc5acf90dc497cb0
次回 => https://qiita.com/theFirstPenguin/items/b5f6ed253bed95fbec5a
今日の学びをメモ
ローカルPC上でnode.jsでexpressを実行するコンテナとnginxを実行するコンテナを立ち上げる。そしてnginxを経由してexpressのAPIを叩く。たったこれだけをdocker-composeを使ってやってみた。
前回までと今回の違い
前回ではexpressのコンテナにアクセスするためにportを指定する必要があった。
curl http://localhost:3000
Hello
今回はnginxのproxy機能を用いて、portを指定せずexpressのコンテナにアクセスできるようにした。
curl http://:localhost
Hello
開発の全体像
cd ~
mkdir sample
sampleディレクトリの中で開発する。ディレクトリの中身はこんな感じになる。
appディレクトリとwebディレクトリがそれぞれexpressとnginxのコンテナとなる。
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello').status(200);
});
app.listen(3000, () => {
console.log('Listening on port 3000');
});
expressバックエンドのDockerfileの準備
FROM node:alpine
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm ci --only=production
# Bundle app source
COPY . .
# package.jsonをコピー後にnpm installするという作業をビルドの度に毎回やりたくない。
# そのため、上記を終わらせてから COPY. .をやる。
# そうすればコードを変えた部分だけビルドが実行される。
EXPOSE 3000
CMD [ "node", "index.js" ]
nginx.confの準備
nginxコンテナの中の、localhostの80port(つまりhttpのデフォルトport)の全てのエンドポイント(/)に来たリクエストをhttp://app:3000
にproxyする。
Dockerの管理下において、appコンテナのドメインがappになっていることに注目。
ちなみに、この設定ファイル名はnginx.conf
で固定とのこと。配置場所はwebディレクトリ以下であれば特に気にしない。
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
}
http {
# Weather Report Reverse Proxy
server {
listen 80;
server_name localhost 127.0.0.1;
location / {
proxy_pass http://app:3000;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
docker-compose.ymlの準備
version: '3'
# 何も考えず3を指定
services:
app:
build:
context: ./app
# docker-compose.ymlから見て./appにあるDockerfileにしたがってビルドする
container_name: express-app
# 一応コンテナ名をつける
ports:
- '3000:3000'
# docker run -p 3000:3000 app と一緒
volumes:
- './app:/usr/src/app'
# ローカルPCの./appフォルダと、コンテナ内の ~/usr/src/appフォルダを同期させる。
# docker exec -it express-app sh で確認できる
web:
image: nginx:latest
#nginx:alpilneだとエラーが起きるので、一応最新版で対応。
container_name: nginx-web
ports:
- '80:80'
volumes:
- './web/reverse_proxy/nginx.conf:/etc/nginx/nginx.conf'
# ローカルPCの./web/reverse_proxy/nginx.confと、コンテナ内の ~/etc/nginx/nginx.confを同期させる。
# ~/etc/nginx/nginx.confは場所指定。
links:
- app
depends_on:
- app
# appコンテナが起動しないと機能しない、という依存関係を明記。
docker-compose up して終わり
docker-compose up
すればコンテナが立ち上がります。
ローカルPCからcurlコマンドを打てばappコンテナから返事が帰ってきます。最初の図の通りです。
curl http://localhost
Hello
ちなみに直接appコンテナにもアクセスできます。当然ですが。
curl http://localhost:3000
Hello
最後に
初歩中の初歩をまとめました。
ちなみに、自分は何度やってもnginxがうまく起動せず絶望しかけましたが、docker ps
をするとk8s_controller_ingress-nginx-controller
という謎のコンテナ(というかkubernetesのingressだと思われる)がdocker stop
しても止まらないことに気付きました。kubernetesを再起動すると直ったので、仮にそんな状況があれば試すのもいいかと思います。
ありがとうございました。