3
2

More than 3 years have passed since last update.

【Docker】 「Hello from Docker!」から半歩進んでみる

Last updated at Posted at 2021-03-09

この記事の目的

  • Docker初心者が「Hello from Docker!」の半歩先に進む手助けをすることで、コンテナやDockerに慣れてもらう
  • Dockerを使って簡単なWebページを表示する

ターゲット

  • インストールだけはしたけど使い方が分からない人
  • 難しいことはいいから、とりあえず動かしたい人

前提条件

  • Dockerをインストールしている
  • hello-world(公式イメージ)などで動作確認が出来ている

※インストールがまだの方は以下の記事を参考にして下さい
Windows 10 64-bit: Pro, Enterprise, Educationの場合
Windows10 ProにDocker Desktopをインストールする

Windows 10 Homeの場合
Windows 10 HomeへのDocker Desktop (ver 3.0.0) インストールが何事もなく簡単にできるようになっていた (2020.12時点)

macOSの場合
Dockerインストール手順<macOS向け>

動作確認

インストールしてから時間が経って忘れてしまっている方のウォーミングアップも含めて、hello-worldを実行してみましょう。

hello-worldの実行
$ docker run hello-world

以下の通りに出力されれば成功です。
(すでに一度実行している場合は、Hello from Docker! から下が出力されます。)

hello-worldの結果
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete
Digest: sha256:89b647c604b2a436fc3aa56ab1ec515c26b085ac0c15b0d105bc475be15738fb
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Webアプリを構築する

先ほどはDocker公式が用意しているhello-worldを使いました。
今回は、Goという言語でHello World!が表示されるWebアプリを構築しましょう。
構築手順は、大まかに以下の通りです。

  1. GoでWebアプリ作成
  2. Dockerfile作成
  3. DockerfileからDockerイメージを作成
  4. DockerイメージからDockerコンテナを作成・実行

Dockerfile、Dockerイメージ、Dockerコンテナの説明や関係性は後ほど簡単に説明しますが、先に詳しく知りたい方は以下のサイトがおすすめです。
Dockerイメージの理解を目指すチュートリアル

GoでWebアプリ作成

下記のサイトを参考に、画面にHello World!を表示するWebアプリを作成します。
Go / Gin で超簡単なWebアプリを作る

作成するWebアプリのディレクトリ構成は以下です。

フォルダ構成
任意のフォルダ
│
└─go
    │ ★ go.mod
    │
    └─src
        │ ★ main.go
        │
        └─templates
               ★ index.html

上から順に作成します。今回はGoの学習がメインではありませんので、コピーで構いません。

go.mod
module m

go 1.16

require github.com/gin-gonic/gin v1.6.3
main.go
package main

import (
    "github.com/gin-gonic/gin"
)

func main() {
    router := gin.Default()
    router.LoadHTMLGlob("/go/src/templates/*.html")

    router.GET("/", func(ctx *gin.Context) {
        ctx.HTML(200, "index.html", gin.H{})
    })

    router.Run()
}
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Go App in Docker</title>
</head>
<body>
    <h1>Hello World!</h1>
</body>
</html>

Dockerfileを作成

Dockerfileをgoフォルダと同階層に作成します。

Dockerfileの場所
任意のフォルダ
│ ★ Dockerfile
│
└─go
    │  go.mod
    │
    └─src
        │  main.go
        │
        └─templates
                index.html

Dockerfileってなに?

Dockerfileとは、Dockerイメージを作成するための定義ファイル(設計書みたいなもの)です。Dockerfileをビルド(build)するとDockerイメージを作成出来ます。

今回は、任意のフォルダに以下のDockerfileを作成してください。ファイル名を「Dockerfile」として下さい。

Dockerfile
# golang v1.16.0をベースイメージに指定
FROM golang:1.16.0
# Docker内での作業ディレクトリを指定
WORKDIR /go
# go.modをコピー
COPY ./go/go.mod ./
# Go modulesの設定
ENV GO111MODULE=on
# Go modulesを使用するため、GOPATHは削除
ENV GOPATH=
# Goの依存パッケージダウンロード
RUN go mod download
# Webアプリを作業ディレクトリにコピー
COPY ./go/src/ ./src/
# 待ち受けポートを8080に指定
EXPOSE 8080
# アプリ起動コマンド
CMD ["go", "run", "./src/main.go"]

Dockerfileについて詳しく知りたい方は折りたたみを読んで下さい。

Dockerfileを読み解く

Dockerfileを読み解く

Dockerfileにコメントもありますが、理解を深めるために詳しく説明していきます。

# golang v1.16.0をベースイメージに指定
FROM golang:1.16.0

FROMは、基本的にはDockerfileの最初に記述するコマンドで、タグを用いてベースイメージを指定します。ベースイメージとは、公式などがDocker Hubというリポジトリに公開している汎用的なDockerイメージです。
Dockerfileを作成する際に全てを定義するのは大変なので、自分の用途に適したベースイメージをDocker Hubから探して、2行目以降でカスタマイズします。
今回はGo言語でアプリを作成しますので、golang:1.16.0というタグを指定しています。
どのようなタグでベースイメージを取得できるかは、こちらで確認できます。

# Docker内での作業ディレクトリを指定
WORKDIR /go

Docker内での作業ディレクトリを指定します。
以降のCOPY命令の右側やCMD命令で./と書かれているものは、/goとなります。

# go.modをコピー
COPY ./go/go.mod ./

COPYは、ファイルパスやフォルダパスを指定してコピーするコマンドです。
今回は、Dockerファイルがあるフォルダ配下の./go/go.modを、Dockerの./(/go)にコピーしています。

# Go modulesの設定
ENV GO111MODULE=on
# Go modulesを使用するため、GOPATHは削除
ENV GOPATH=

ENVは、環境変数を設定する命令です。今回は、Goのアプリに必要な環境変数を設定しています。

# Goの依存パッケージダウンロード
RUN go mod download

RUNは、Dockerでコマンドを実行する命令です。デフォルトではshell形式で指定して、shell内で実行されます。(その他の方法で実行したい場合はこちら)
今回は、go.modに記述した依存パッケージをダウンロードしています。

# Webアプリを作業ディレクトリにコピー
COPY ./go/src/ ./src/

go.modの時と同様にsrcフォルダをコピーしています。
なんで分けてコピーしてるのかについては説明すると長くなってしまうので省きます。気になる方は以下のリンク先の「おまけ COPYのコツ」を読んでみてください。
DockerfileにてなぜADDよりCOPYが望ましいのか

# 待ち受けポートを8080に指定
EXPOSE 8080

EXPOSEは、待ち受けポートを指定する命令です。今回は8080としています。

# アプリ起動コマンド
CMD ["go", "run", "./src/main.go"]

CMDは、RUNと同様にコマンドを実行する命令です。違いは実行のタイミングです。

命令 実行のタイミング
RUN イメージを作成時に実行
CMD イメージ作成後、コンテナ実行時に実行

GOのWebアプリはコンテナが作成されてから実行して欲しいので、CMD命令で記述しています。
CMD命令は、Dockerfile内で1つしか記述出来ません。複数行記述した場合は、ビルド時に警告が出て最後のコマンドのみ実行されますので注意してください。

DockerfileからDockerイメージを作成

DockerfileというDockerイメージの設計書が完成したので、次はイメージを作成します。
任意のフォルダ直下(Dockerfileがある場所)で以下のコマンドを実行して下さい。

Dockerイメージ作成
$ docker build . -t go-app

コマンドの意味はこんな感じです。
docker build <Dockerfileのファイルパス> -t <名前:タグ>
今回は、Dockerfileと同階層でコマンドを実行しているので、.です。
名前というのは、Dockerイメージを識別するための名前です。タグは、バージョンなどを表すために付けます。今回は名前をgo-appと指定して、タグは省略したためlatestとなります。

では、作成したDockerイメージを確認しましょう。

Dockerイメージを確認
$ docker images

以下のような出力結果ならばDockerイメージが作成出来ています。

Dockerイメージ確認結果
REPOSITORY    TAG                 IMAGE ID       CREATED          SIZE
go-app        latest              463ccbe513cf   37 seconds ago   969MB
hello-world   latest              d1165f221234   1 hours ago     13.3kB
......(省略)

REPOSITORYがgo-appとなっています。Dockerイメージの「名前」や「イメージ名」と説明があったら、基本的にREPOSITORYに表示されている値を指します。

DockerイメージからDockerコンテナを作成・実行

いよいよWebアプリを動かせます!
以下のコマンドでDockerイメージからDockerコンテナを作成・実行しましょう。

Dockerコンテナ作成・実行
$ docker run -p 8080:8080 go-app

DockerイメージからDockerコンテナを作成・実行するときは、runコマンドを使用します。
今回のコマンドの意味は以下です。
docker run -p <ローカルのポート>:<Dockerコンテナのポート> <イメージ名>
-pは、ローカルとDockerコンテナ内部のポートを繋げるためのオプションです。

DockerコンテナとWebアプリの確認

最後にDockerコンテナとWebアプリの動作確認です。
Listening and serving HTTP on :8080と出力されたらlocalhost:8080にアクセスしてみましょう。
ブラウザの画面左上に「Hello World!」が表示されます!

後片付け

このままでは、Dockerコンテナが起動したままになってしまいます。またDockerイメージなども使わないならば削除しておいた方が良いです。(Dockerfileがあればまた作ることが出来ます。)

まずは、以下のコマンドを実行して起動中のDockerコンテナを確認します。

起動中Dockerコンテナ確認
$ docker ps

以下のように何らかの出力がある場合は、停止する必要があります。

起動中Dockerコンテナ確認結果
CONTAINER ID   IMAGE     COMMAND                  CREATED              STATUS              PORTS                    NAMES
ece7970bbafd   go-app    "go run /go/src/main…"   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp   bold_khayyam

上記の出力でCONTAINER IDを確認して、go-appのDockerコンテナを停止します。

Dockerコンテナ停止
$ docker stop {CONTAINER ID}

今回の例では、{CONTAINER ID} = ece7970bbafd です。
もう一度起動中のDockerコンテナを確認します。

起動中Dockerコンテナを再度確認
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

何も表示されていなければ停止しています。

次にDockerコンテナを削除します。-aのオプションを使うと、起動中のコンテナだけでなく停止中のコンテナを含めて確認出来ます。

Dockerコンテナを確認
$ docker ps -a

以下のようにSTATUSExitedで、先ほど停止したコンテナが出力されると思います。

Dockerコンテナ確認結果
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
ece7970bbafd   go-app    "go run /go/src/main…"   12 minutes ago   Exited (2) 6 minutes ago              bold_khayyam

以下のコマンドを実行してコンテナを削除します。

Dockerコンテナを削除
$ docker rm {CONTAINER ID}

もう一度Dockerコンテナを確認します。

Dockerコンテナを再度確認
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

何も表示されていなければDockerコンテナの後片付けは完了です。

イメージも同様に片付けましょう。
以下のコマンドを実行して、Dockerイメージを確認してください。

Dockerイメージを確認
$ docker images

go-appのイメージがあると思います。

Dockerイメージ確認結果
REPOSITORY    TAG                 IMAGE ID       CREATED             SIZE
go-app        latest              463ccbe513cf   About an hour ago   969MB
hello-world   latest              d1165f221234   41 hours ago        13.3kB
......(省略)

Dockerイメージも削除しましょう。

Dockerイメージを削除
$ docker rmi {IMAGE ID}

今回の例では、{IMAGE ID} = 463ccbe513cf です。
以下のように出力されれば後片付け完了です。

Dockerイメージ削除結果
Untagged: go-app:latest
Deleted: sha256:463ccbe513cff171877c411423843e2bbc9d6eb1f52e7f59b0f0e857b47fc714

まとめ

いかがだったでしょうか?慣れない作業が多く、疲れてしまった方も多いと思います。
確かにDockerをはじめとしたコンテナ技術は、簡単なシステムの作成にはオーバーヘッドが大きいのでありがたみを感じられなかったかもしれません。
しかし、複雑なシステムを扱うほど問題となる環境構築などを簡単にすることが出来ますので、これからも興味を持って頂ければと思います。

参考サイト

Windows10 ProにDocker Desktopをインストールする
Windows 10 HomeへのDocker Desktop (ver 3.0.0) インストールが何事もなく簡単にできるようになっていた (2020.12時点)
Dockerイメージの理解を目指すチュートリアル
[Docker] Dockerfile を作って Web アプリを構築する
Golang - Dockerfileの最小構成
Go / Gin で超簡単なWebアプリを作る
DockerfileにてなぜADDよりCOPYが望ましいのか

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2