docker入門 その2(簡易WEBサーバー立ち上げ)

前回その1では事前準備としてGCPのVMインスタンスにdockerをインストールする手順を紹介しました。

その2である今回はdockerを使って簡単なWEBサーバーを構築してみたいと思います。

dockerでWEBサーバーを構築する手順を紹介する記事は数多ありますが、この記事はそれらの記事とは少しだけ違います。

と言いますのも、docker入門記事でWEBサーバー構築となると、まずはdockerコマンドを使う方法が大半ですが、この記事ではdockerコマンドは使わずに最初からdocker-composeを使って構築します。

dockerコマンドは色々な記事や書籍で使い方を説明されていますが、オプションを覚えるのが面倒であり、オプションをYAMLファイルで設定できるdocker-composeの方が使い勝手がいいので、dockerコマンドの説明はスキップします。(dockerコマンドについて詳しく知りたい方は別のサイトをあたっていただけると・・・)

というわけでdocker-composeを使ってWEBサーバーを構築する手順をこれから紹介します。

ステップ1(最小限の設定)

docker-composeの設定ファイルは先ほど触れましたがYAML形式で記述します。

まず最初は最小限の設定です。「nginx」という既存のコンテナイメージを使ってwebというサービスを作成しなさいという設定です。

version: '3'
services:
  web:
    image: nginx

上記YAMLファイルがあるディレクトリでコマンドを実行します。

# コンテナをビルド(今回は既存のイメージをそのまま使うのでビルドはスキップされる)
$ sudo docker-compose build
web uses an image, skipping
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/

# コンテナを起動(デーモン化)
$ sudo docker-compose up -d
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Creating network "web_default" with the default driver
Pulling web (nginx:)...
latest: Pulling from library/nginx
45b42c59be33: Pull complete
8acc495f1d91: Pull complete
ec3bd7de90d7: Pull complete
19e2441aeeab: Pull complete
f5a38c5f8d4e: Pull complete
83500d851118: Pull complete
Digest: sha256:f3693fe50d5b1df1ecd315d54813a77afd56b0245a404055a946574deb6b34fc
Status: Downloaded newer image for nginx:latest
Creating web_web_1 ... done

# コンテナの状態を確認
$ sudo docker-compose ps
  Name                 Command               State   Ports 
-----------------------------------------------------------
web_web_1   /docker-entrypoint.sh ngin ...   Up      80/tcp

# コンテナ内部のログ(標準出力)を確認
$ sudo docker-compose logs
Attaching to web_web_1
web_1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web_1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web_1  | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
web_1  | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
web_1  | /docker-entrypoint.sh: Configuration complete; ready for start up

コンテナが起動した状態でクライアントPCから接続してみます。

今回はSSHポートフォワーディングを使って安全な状態でWEBサーバーに接続します。

$ gcloud compute ssh --project (project_id) --zone (zone) (instance_name) -- -L 8080:localhost:80

ではブラウザで「http://localhost:8080」にアクセスしてみましょう。

あれ、、、接続できない。

はい、これは意図した動きです。コンテナの外からコンテナに接続する場合は明示的にポートを公開する設定をしないといけません。

ですので、次はポートの公開設定をします。

ステップ2(ポート公開設定)

ポートを公開する設定をdocker-compose.ymlに追加します。コンテナの80番ポートに対して80番ポートをマッピングして接続できるようにします。

version: '3'
services:
  web:
    image: nginx
    ports:
      - "80:80"

コマンドを実行します。

# コンテナを起動(再起動)
$ sudo docker-compose up -d
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Recreating web_web_1 ... done

# コンテナの状態を確認
$ sudo docker-compose ps
  Name                 Command               State         Ports       
-----------------------------------------------------------------------
web_web_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp

再度「http://localhost:8080」にアクセスすると見覚えのあるページが表示されます。

しかし、ページは表示されたものの自分が表示したいコンテンツが表示されず、これでは使い物になりません。

次に自分が表示したいコンテンツを表示させます。

ステップ3(コンテンツ追加)

ステップ3ではdocker-compose.ymlに加えてDockerfileも登場します。

最初にこのステップで表示したいコンテンツとなるhtmlファイルを作成します。

Hello, nginx!

Dockerfileはコンテナの構築する手順を記した定義ファイルです。このファイルでは「nginx」イメージをベースとし、nginxのhtml設置フォルダに独自のindex.htmlをコピーします。

FROM nginx
COPY index.html /usr/share/nginx/html

docker-compose.ymlでbuildオプションにDockerfileがあるフォルダ(今回はカレントディレクトリ)を指定します。

version: '3'
services:
  web:
    build: .
    ports:
      - "80:80"

コマンドを実行します。

# コンテナをビルド(今回はDockerfileを使っているので必須)
$ sudo docker-compose build
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Building web
Sending build context to Docker daemon  4.096kB

Step 1/2 : FROM nginx
 ---> 35c43ace9216
Step 2/2 : COPY index.html /usr/share/nginx/html
 ---> cc4f66ec729d
Successfully built cc4f66ec729d
Successfully tagged web_web:latest

# コンテナを起動(再起動)
$ sudo docker-compose up -d
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Recreating web_web_1 ... done

# コンテナの状態を確認
$ sudo docker-compose ps
  Name                 Command               State         Ports       
-----------------------------------------------------------------------
web_web_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp

ブラウザからhttp://localhost:8080にアクセスすると、

無事にindex.htmlの内容が表示されました。

しかし、この場合コンテンツを修正する度にコンテナをビルドし直す必要があり、頻繁にコンテンツを修正する際に面倒だったりします。

そこでコンテナとホストでフォルダを共有し、コンテンツの修正がリアルタイムにコンテナに反映されるようにします。

ステップ4(ディレクトリ共有)

このステップでは、フォルダを共有してコンテンツを書き換えられるようにします。

ステップ2時点でのdocker-compose.ymlにフォルダ共有設定を加えます。docker-compose.ymlが存在するフォルダに新たにsrcフォルダを作成し、その中にステップ3で作成したindex.htmlを移動します。srcフォルダを/usr/share/nginx/html(nginxのドキュメントルート)にマウントさせます。

version: '3'
services:
  web:
    image: nginx
    ports:
      - "80:80"
    volumes:
      - ./src:/usr/share/nginx/html

コマンドを実行します。

# ファイルの一覧
$ ls
docker-compose.yml  src

# srcフォルダの中の一覧
$ ls src
index.html

# コンテナの起動(再起動)
$ sudo docker-compose up -d
Building with native build. Learn about native build in Compose here: https://docs.docker.com/go/compose-native-build/
Recreating web_web_1 ... done

# コンテナの状態を確認
$ sudo docker-compose ps
  Name                 Command               State         Ports       
-----------------------------------------------------------------------
web_web_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp

「http://localhost:8080」にアクセスすると、ステップ3と同じコンテンツが表示されます。

ここでindex.htmlの内容を書き換えます。(Hello, nginx!→Hello, docker!)

$ vim src/index.html

「http://localhost:8080」にアクセスすると、書き換えた内容が表示されます。

終わりに

今回はdocker(正確にはdocker-compose)を使って簡単なWEBサーバーを構築する手順を紹介しました。これからdockerを覚えようという方の参考になれば!

次回はもう少し複雑なサーバーを構築する手順を紹介できればと思います。