エンジニアを目指す日常ブログ

日々勉強したことのメモ。独学ですので間違っていたらコメント等で教えてください。

docker-composeを利用してdockerコンテナを作成する方法メモ(複数コンテナ対応)

はじめに

本記事の目的

dockerコンテナを立ち上げる。 また、今回はdocker-composeというツールも利用する。

基礎知識として、docker-composeツールを使わずにDockerを立ち上げる方法は以下の記事に記載している。 いかの記事ではAWSのEC2上で実施しているが、もちろんEC2を使わずローカルで実施も可能。
EC2サーバ(Linux)上でdockerコンテナを起動する方法メモ(nginxベース) - エンジニアを目指す日常ブログ

前提

  • Linux環境とする。

今回はWindows上にVagrantで仮想環境を用意している。 tomiko0404.hatenablog.com

dockerインストール

以下サイトを参考に実施した。

Vagrantの上にDockerを載せて開発環境を作成する(おそらくこちらを見ながらやったはず)
Ubuntuにdockerをインストールする - Qiita

docker-composeもインストールが必要。

Docker Compose のインストール | Docker ドキュメント

Dockerfileの作成

Dockerfileとは、dockerイメージファイルを作るときに元ネタとなる設定値を記載するファイル。 dockerイメージはdockerコンテナの設計図のようなもので、基本的にdockerは、

  1. Dockerfileに従ってdockerイメージをビルド
  2. dockerイメージに従ってコンテナを作成

という流れでコンテナを作成する必要がある。

今回はDockerfileを以下のように記述した。

FROM node:14.15.4-slim

RUN apt-get update && apt-get install -y locales \
    && locale-gen en_US.UTF-8 \
    && localedef -i en_US -f UTF-8 en_US.UTF-8 \
    && echo "export LC_ALL=en_US.UTF-8" >> ~/.bashrc \
    && ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

RUN apt-get install -y \
    wget \
    curl \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

一番上の

FROM node:14.15.4-slim

は、dockerhubという、コンテナイメージの倉庫のようなところから既存のイメージを持ってくるための記載。

今回はNode.jsを利用してアプリを作りたいので、Node.jsのイメージを持ってくる。

■docker hubの node ページ。 hub.docker.com ■nodeのReadmeページ。Dockerfileの書き方例なども載っている。 github.com

docker-compose.ymlファイルの作成

docker-composeは、一言でいえば「Docker構築を楽にするためのツール」である。

docker-composeツールを使うと、コマンド docker-compose up一つで「Dockerfileに従ってdockerイメージをビルド」⇒「dockerイメージに従ってコンテナを作成」を実行してくれる。

その際の設定値を規定するのがdocker-compose.ymlである。 dockerの各種コマンド(イメージをビルドするコマンドや、コンテナ起動するコマンド)の引数をdocker-compose.ymlで事前に定義しておくイメージ。

今回作成したdocker-compose.ymlファイル

今回は、「画面サーバ」と「Webサーバ」を用意したいので、2つのコンテナを立ち上げたい。 記載内容は以下となる。

docker-compose.yml

# このファイルはversion3の書き方仕様で書いてますよという宣言。おまじない扱いで良い。
version: '3'

# networkを作成する。複数のコンテナどうしでネットワークを構成したいときに
# 作成する。基本はbridgeを利用する。「react_net」は自分で設定したネットワーク名。
networks:
  react_net:
    driver: bridge

# 作りたいサービスを規定する。
# 今回は「frontend」と「backend」の2つのサービスを作成。
services:
  frontend:   # サービス名
    build: ./   # Dockerfileを利用してイメージをbuildする。Dockerfileの場所を記載する。
    image: react_front   #  buildしたイメージの名前を決める。
    container_name: frontend   # 起動するコンテナの名前を決める。
    tty: true   # 調査中
    volumes:
      - ../front:/app   # ローカルの ../front フォルダを、コンテナ上の/appフォルダにマウントする
    working_dir: "/app"   # コンテナが立ち上がったときに最初にいるフォルダの場所を決める
    ports:
      - 8000:8000   # ローカルの8000ポートとコンテナの8000ポートをポートフォワーディング
    networks:
      - react_net   # 上で定義したreact_netネットワークに接続する

  backend:
    build: ./
    image: node_back
    container_name: backend   # コンテナ名は別名を設定する
    tty: true
    volumes:
      - ../back:/app
    working_dir: "/app"
    ports:
      - 3000:3000 # ポートフォワーディングもかぶらないよう設定
    networks:
      - react_net

コンテナ1つで良い場合

コンテナ1つで良い場合は、以下の記載とする。

version: '3'

networks:
  react_net:
    driver: bridge

services:
  frontend:
    build: ./
    image: react_front
    container_name: frontend
    tty: true
    volumes:
      - ../:/app
    working_dir: "/app"
    ports:
      - 8000:8000
    networks:
      - react_net

docker-compose.ymlの記載内容について

各種設定の中身は以下記事が参考になる。 【Docker】初心者のための Docker Compose まとめ - AI can fly !!

参考:Dockerfileを利用しない方法

上記参考記事のimageオプションの解説を見ると以下の記載がある。

前述の build が指定されている場合は、 build で指定された Dockerfile から Docker イメージが構築され、そのイメージ名が image で指定した名前になります。 build を指定しない (Dockerfile からイメージを構築しない) 場合、ここで指定された Docker イメージからコンテナを作成しますが、指定した Docker イメージがローカルに存在しない場合は、 Docker Hub から Pull (取得) した上でコンテナが作成されます。

今回はbuildコマンドで自作のDockerfileを指定しているが、単純に

image: node:14.15.4-slim

と記載しても問題ない。この場合Dockerfileが不要になる。

イメージをビルドし、コンテナを作成する

(事前確認)dockerイメージの存在確認

今あるdockerイメージを確認する。

dockerイメージを確認するコマンド:docker images

$ sudo docker images

過去に作ったものが残っていた。nodeは公式イメージ。

REPOSITORY         TAG            IMAGE ID       CREATED        SIZE
react-practice-6   latest         d4a0b79d2c36   3 weeks ago    473MB
node               14.15.4-slim   2f75d89d8162   8 months ago   167MB

イメージ作成とコンテナ起動

以下のコマンドを実行する。

$ sudo docker-compose up -d

イメージが作られたことの確認

docker-compose.ymlで指定した名前のdockerイメージが作成された。

$ sudo docker images
REPOSITORY         TAG            IMAGE ID       CREATED              SIZE
node_back          latest         e6e824760f03   About a minute ago   216MB
react_front        latest         e6e824760f03   About a minute ago   216MB
react-practice-6   latest         d4a0b79d2c36   3 weeks ago          473MB
node               14.15.4-slim   2f75d89d8162   8 months ago         167MB

コンテナが起動したことの確認

  • 起動中のコンテナを確認するコマンド:docker ps
  • 起動中に限らずコンテナを確認するコマンド:docker ps -a

frontendコンテナとbackendコンテナが起動された。

$ sudo docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS                                       NAMES
fce6328cdc9f   react_front   "docker-entrypoint.s…"   3 minutes ago   Up 3 minutes   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp   frontend
3eb02504a2a0   node_back     "docker-entrypoint.s…"   3 minutes ago   Up 3 minutes   0.0.0.0:3000->3000/tcp, :::3000->3000/tcp   backend

コンテナの中に入って操作する

コンテナの操作は基本的に'docker exec'で実施することができる。 毎回書くのは大変なので以下コマンドでターミナルを立ち上げることができる。

$ sudo docker exec -u node -it frontend /bin/bash -l

docker execの構文は以下の通りである。

$ docker exec [オプション] [コンテナ名] [コマンド] [引数...]

-u nodeはユーザ名を指定している。今回は公式のnodeイメージのデフォルトユーザ名nodeを指定。 -itは対話型を指定するオプション。 frontendはコンテナ名。 /bin/bash -lが実行したいコマンドとなる。

コンテナから抜ける

コンテナから抜けたいときはexitコマンドで抜けられる。

コンテナを停止する

コンテナを停止したいときは

$docker-compose down

【補足】コンテナ上でアプリを実行してみる

Node.jsで簡単なHTTPサーバが動くか確認。 コンテナと共有しているフォルダにapp.jsを作成する。

ローカルのフォルダ構成

ローカルのフォルダ構成は以下のようになっている。

.
├── back     ※backendのdockerにマウント
│   └── app.js
├── docker
│   ├── Dockerfile
│   └── docker-compose.yml
└── front      ※frontendのdockerにマウント(今は空)

app.jsの作成

app.js

const portNumber = 8000;
const http = require("http");

http.createServer((req, res) => {
    res.writeHead(200, { "Content-Type": "text/plain" });
    res.end("Hello World");
}).listen(portNumber);

console.log(`PortNumber is ${portNumber}`);

app.jsを実行

コンテナに入った状態で以下を実行する。

node@fce6328cdc9f:/app$ node app.js

ブラウザからlocalhost:8000にアクセスすると応答が返ってくる。

応答が返ってくる
応答が返ってくる

今回は、Node.jsのみで実行できるアプリのため、app.jsを作成するだけで実行できる。追加モジュールが必要な場合は、npm installなどで追加する必要がある。

おわりに

docker-composeを利用してコンテナを立ち上げる方法をメモした。

以前にも同じような記事を書いたが、この理解度で複数のコンテナを立ち上げようとしたら行き詰ってしまったので、docker-composeについて勉強しました。 結果、理解が深まったので整理がてら書き直したのが本記事です。

以前の記事
vagrant上にdockerコンテナを立ち上げる方法メモ(docker-compose利用) - エンジニアを目指す日常ブログ

関連記事

つづき:WebAPIサーバの開発

上記のapp.jsの続きで、Node.jsでWebAPIサーバを作成した。

tomiko0404.hatenablog.com

つづき:フロントエンドの開発

dockerコンテナ上にReactアプリ作成した。

tomiko0404.hatenablog.com

参考資料

dockerコマンドが豊富な記事。

Dockerイメージとコンテナの削除方法 - Qiita