Dockerについて記事を書くのは3回目です。
コンテナ未経験なのでDockerを基礎から学んでみた
DockerコンテナでNode.jsを実行してみた
今回はDocker Composeを使い、Node.jsとRedisからなる簡単な"訪問者カウンター"を作ってみました。
Docker Composeって何?
複数のコンテナからなるシステムを簡単に構築するためのツールです。YAMLファイルを使ってアプリケーションサービスの設定を行い、コマンドを1つ実行するだけで、設定内容に基づいたアプリケーションサービスの生成・起動を行うことができます。
システム構築
Docker Composeを使わずに構築トライ
package.json
とindex.js
とDockerfile
を作成します。
{"dependencies":{"express":"*","redis":"2.8.0"},"scripts":{"start":"node index.js"}}
index.js
のapp.getの中で、redisへの訪問者数(visits)の保存とカウントを行います。
constexpress=require('express');constredis=require('redis');constapp=express();constclient=redis.createClient();client.set('visits',0);app.get('/',(req,res)=>{client.get('visits',(err,visits)=>{res.send('Number of visits is '+visits);client.set('visits',parseInt(visits)+1);});});app.listen(8081,()=>{console.log('Listening on port 8081');});
また、Dockerfile
では、ベースイメージをnode:alpine
とし、ファイルのコピー先を'/app'と指定しています。
FROM node:alpineWORKDIR '/app'COPY package.json .RUN npm installCOPY . .CMD ["npm", "start"]
docker run redis
でredisのコンテナを起動した後に、ターミナルの別タブを開いて、作成したDockerfileからイメージのビルド(docker build -t suzuki0430/visits:latest .
)とコンテナ起動(docker run suzuki0430/visits
)を行います。
すると、redis-serverとの接続ができないというエラーがでます。
Error: getaddrinfo ENOTFOUND redis-server
コンテナプロセスは独立して動いているので、各コンテナを接続したい場合はそれに関する設定を行う必要があります。
ここで使用するのがDocker Composeです。
Docker Composeを使って構築トライ
複数のDockerコンテナを同時起動するために、docker-compose.yml
ファイルを以下のように記述します。
version: '3' // docker-composeのバージョン
services: // 起動したいコンテナの種類
redis-server:
image: 'redis' // redisイメージでコンテナを起動
node-app:
build: . // カレントディレクトリのDockerfileからイメージをビルドしてコンテナを起動
ports: // ポートマッピング([localhostのポート番号]:[コンテナのポート番号])
- '4001:8081'
また、redis-server
とnode-app
の接続を行うために、index.js
に以下を追記します。6379はredisのデフォルトポート番号です。
constclient=redis.createClient({host:'redis-server',port:6379,});
Docker Composeはdocker-compose CLIのコマンドで操作します。
docker-compose up
: コンテナ起動docker-compose up --build
: イメージビルド + コンテナ起動docker-compose up -d
: バックグラウンでコンテナ起動docker-compose down
: コンテナ停止docker-compose ps
: プロセス確認
docker-compose up
を実行してみると、node-app
とredis-server
のコンテナが起動します。
(base) [16:12:32] → docker-compose up ~/Programs/docker/visits
Recreating visits_node-app_1 ... done
Starting visits_redis-server_1 ... done
Attaching to visits_redis-server_1, visits_node-app_1
redis-server_1 | 1:C 06 Mar 2021 07:12:39.624 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-server_1 | 1:C 06 Mar 2021 07:12:39.624 # Redis version=6.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis-server_1 | 1:C 06 Mar 2021 07:12:39.624 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-server_1 | 1:M 06 Mar 2021 07:12:39.626 * Running mode=standalone, port=6379.
redis-server_1 | 1:M 06 Mar 2021 07:12:39.626 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis-server_1 | 1:M 06 Mar 2021 07:12:39.626 # Server initialized
redis-server_1 | 1:M 06 Mar 2021 07:12:39.627 * Loading RDB produced by version 6.0.9
redis-server_1 | 1:M 06 Mar 2021 07:12:39.627 * RDB age 10216869 seconds
redis-server_1 | 1:M 06 Mar 2021 07:12:39.627 * RDB memory usage when created 0.79 Mb
redis-server_1 | 1:M 06 Mar 2021 07:12:39.627 * DB loaded from disk: 0.001 seconds
redis-server_1 | 1:M 06 Mar 2021 07:12:39.627 * Ready to accept connections
node-app_1 |
node-app_1 | > start
node-app_1 | > node index.js
node-app_1 |
node-app_1 | Listening on port 8081
以下の部分で、コンテナ同士の接続も確認することができます。
Attaching to visits_redis-server_1, visits_node-app_1
ブラウザでlocalhost:4001
に接続すると、ちゃんと開けました。
Docker Composeの自動再起動
システムの構築は完了したのですが、Docker Composeの理解を深めるために自動再起動の方法についても学びました。
index.js
のapp.getでprocess.exit(0)
を記述し、node-app
のプロセスを終了するようにします。
constprocess=require('process');app.get('/',(req,res)=>{process.exit(0);});
次にdocker-compose.yml
にrestart: always
を加えます。
version: '3'
services:
redis-server:
image: 'redis'
node-app:
restart: always
build: .
ports:
- '4001:8081'
docker-compose up --build
でイメージビルドとコンテナ起動を再実行してlocalhost:4001
にアクセスすると、プロセス終了後にコンテナを再起動しようとします。
node-app_1 |
node-app_1 | > start
node-app_1 | > node index.js
node-app_1 |
node-app_1 | Listening on port 8081
visits_node-app_1 exited with code 0
node-app_1 |
node-app_1 | > start
node-app_1 | > node index.js
node-app_1 |
node-app_1 | Listening on port 8081
visits_node-app_1 exited with code 0
restart: always
以外にも以下のような再起動ポリシーがあります。
- "no": 再起動しない
- always: コンテナが停止したらいかなる理由でも再起動する
- on-failure: コンテナがエラーコードをだして停止したら再起動する
- unless-stopped: ユーザがコンテナを強制終了しない限り常に再起動する
おわりに
次はDockerコンテナの本番環境へのデプロイについて学習します。