この記事の目的
- 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を実行してみましょう。
$ docker run hello-world
以下の通りに出力されれば成功です。
(すでに一度実行している場合は、Hello from Docker! から下が出力されます。)
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アプリを構築しましょう。
構築手順は、大まかに以下の通りです。
- GoでWebアプリ作成
- Dockerfile作成
- DockerfileからDockerイメージを作成
- 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の学習がメインではありませんので、コピーで構いません。
module m
go 1.16
require github.com/gin-gonic/gin v1.6.3
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()
}
<!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
│
└─go
│ go.mod
│
└─src
│ main.go
│
└─templates
index.html
Dockerfileってなに?
Dockerfileとは、Dockerイメージを作成するための定義ファイル(設計書みたいなもの)です。Dockerfileをビルド(build)するとDockerイメージを作成出来ます。
今回は、任意のフォルダに以下の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 build . -t go-app
コマンドの意味はこんな感じです。
docker build <Dockerfileのファイルパス> -t <名前:タグ>
今回は、Dockerfileと同階層でコマンドを実行しているので、.
です。
名前というのは、Dockerイメージを識別するための名前です。タグは、バージョンなどを表すために付けます。今回は名前をgo-app
と指定して、タグは省略したためlatestとなります。
では、作成したDockerイメージを確認しましょう。
$ docker images
以下のような出力結果ならば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 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 ps
以下のように何らかの出力がある場合は、停止する必要があります。
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 stop {CONTAINER ID}
今回の例では、{CONTAINER ID} = ece7970bbafd です。
もう一度起動中のDockerコンテナを確認します。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
何も表示されていなければ停止しています。
次にDockerコンテナを削除します。-a
のオプションを使うと、起動中のコンテナだけでなく停止中のコンテナを含めて確認出来ます。
$ docker ps -a
以下のようにSTATUS
Exitedで、先ほど停止したコンテナが出力されると思います。
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 rm {CONTAINER ID}
もう一度Dockerコンテナを確認します。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
何も表示されていなければDockerコンテナの後片付けは完了です。
イメージも同様に片付けましょう。
以下のコマンドを実行して、Dockerイメージを確認してください。
$ docker images
go-appのイメージがあると思います。
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 rmi {IMAGE ID}
今回の例では、{IMAGE ID} = 463ccbe513cf です。
以下のように出力されれば後片付け完了です。
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が望ましいのか