Dockerfileを使用したコンテナ環境の作成について
- dockerを使って、素早く環境構築したい
- dockerfileをもっとスラスラ描きたいという思いから、基本的なことをまとめてみました。
- 下記の書籍を参考にしました。
- Docker/Kubenetes実践コンテナ開入門
- 間違いなどありましたら、コメントにて教えて頂けると、嬉しいです。
Dockerとは
- コンテナ型仮想化技術を実現、操作、管理するためのプロダクト
- コマンドラインで操作
- 良い特徴として
- インストールの難しいツールなどを使う場合でも、ホストを汚さずにDockerコンテナとして実行できる。
- 様々なライブラリやツールをコードで管理することができ、チームで開発環境を統一できる。
- Kubernetesなどを使ってコンテナを管理することにより、より簡単にデプロイやスケールを実現できる。 などなど
DockerイメージとDockerコンテナ
Dockerイメージ
- Dockerコンテナを構成するためのファイルシステムや実行するアプリケーション、設定をまとめたもの。コンテナを作成するためのテンプレート。
DockerHub
- Docker社が管理しているDockerレジストリで、Docker公式のイメージはDockerHubで公開されており、そこからpull(取得)して使う。自分で作成したイメージをDockerHubにpushすることで世界中のユーザに使用してもらうことも可能です。
# イメージ pull
# タグ名は省略可能ですが、省略するとデフォルト(多くの場合latest)が指定されます。
# docker image pull [options] リポジトリ名[:タグ名]
docker image pull golang:1.12
# イメージ push
docker image push [options] リポジトリ名[:タグ]
Dockerコンテナ
- Dockerイメージを基に作成され、アプリケーションが実行されている状態。Dockerによって作成されるゲストOS。
Dockerによる大まかなアプリケーション実行までの流れ
- Dockerイメージを定義...dockerfileを作成
- Dockerイメージを作成...dockerイメージをビルド
- 作成されたDockerイメージを使って、コンテナを作成実行
- コンテナを操作する
- コンテナの停止と開始、再起動と削除
- イメージの削除
1.Dockerイメージを定義...dockerfileの作成
Dockerfileとは
- Dockerイメージを作成するためのスクリプトのことです。イメージを作成するために必要な手順を記載していきます。
# Dockerfile
FROM golang:1.12
RUN mkdir /echo_test
COPY main.go /echo_test
CMD ["go", "run", "/echo_test/main.go"]
// コンテナ実行される、main.goファイル
package main
import (
"fmt"
"log"
"net/http"
)
func main(){
http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request){
log.Println("received request")
fmt.Fprintf(w, "Hello Docker!!")
})
log.Println("start server")
sv := &http.Server{Addr: ":8080"}
if err := sv.ListenAndServe();err != nil{
log.Println(err)
}
}
-
FROM
やRUN
と行ったキーワードを「インストラクション(命令)」と言います。 - Dockerfileではインストラクションを使って、イメージの構成を定義します。
- 上記のDocerfileでやっていること
-
FROM
で作成するDockeイメージのベースとなるイメージを指定しています。この場合、公式のgolang:1.12が指定されていて、golang:1.12のイメージがまだpullされていなければ、DockerHubからpullし、すでにpullされていれば既存のgolang:1.12のイメージを使用します。 -
RUN
でDockerイメージをビルドする時に、Dockerコンテナ内で実行するコマンドを定義しています。この場合、/echo_testというディレクトリをコンテナ内に作成しています。 -
COPY
で、ホストマシン上のファイルやディレクトリをDockerコンテナ内にコピーしています。この場合、Dockerfileと同じディレクトリ内にあるmain.goというファイルをコンテナ内の/echo_testディレクトリにコピーしています。 -
CMD
でDockerコンテナとして実行する際にコンテナ内で実行するプロセスをしています。 CMDはコンテナ起動時に1度実行されます。この場合、以下のようなコマンドを実行してgoのプロセスを実行します。
-
go run /echo_test/main.go
- Dockerfileに記載した各項目(この場合、
FROM
,RUN
,COPY
,CMD
)が、それぞれ1つのレイヤーという単位で、そのレイヤーが重なって、イメージが作成されます。FROMで指定したイメージがベースとなるというのは、このような仕組みのためです。
2.Dockerイメージを作成...Dockerイメージをビルド
- Dockerfileを使用して、Dockerイメージをビルドします。
# docker image build -t イメージ名[:タグ名] Dockerfileのあるディレクトリ
docker image build -t example_go/echo:latest .
-
docer image build
でイメージをビルドします。 -
-t
オプションを必ずつけたほうが良いです。-t
オプションにより、イメージ名を指定することができます。 -
-t
オプション無しでもイメージの作成はできますが、イメージ名(REPOSITORY)とタグ(TAG)の値が<none>
になります。ハッシュ値(IMAGE ID)での管理となり、わかりづらくなります。
$ docker image ls # docker imageの一覧を表示
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> a086e6cb87f0 53 seconds ago 774MB
example_go/echo latest 806faed5d0a8 About an hour ago 774MB
-
docker image ls
コマンドでexample_go/echo
のイメージが作成されていることが確認できました。
3. 作成されたDockerイメージを使って、コンテナを作成実行
- 作成したイメージからコンテナを実行します。
- コマンドは
docker container run イメージ名
となりますが、いくつかオプション指定したほうが良いです。
# docker container run [options] イメージ名:[タグ名]
docker container run -d -p 9000:8080 example_go/echo:latest
- 上記のコマンドを実行後、
localhost:9000
にアクセスするとHello Docker!!
が表示されます。
-
-d
オプションで、コンテナをバックグラウンドで実行します。今回のようなサーバアプリケーションだとバックグラウンドで実行したほうが勝手が良いことが多いと思います。ただrailsなどをコンテナで実行する時に、あえて-d
オプション無しで実行し、logを確認しやすくするようなこともあります。 -
-p
オプションでポートフォワーディングを設定します。今回のアプリケーションは8080のポートで実行されていますが、それはコンテナ内のことで、ポートフォワーディングの設定が無い場合、コンテナの外からポート8080にアクセスしても、コンテナ内のアプリケーションに到達できません。 - コンテナ外からきたリクエストをコンテナ内で実行しているアプリケーションに到達させるために、
-p {ホスト側ポート}:{コンテナ側ポート}
で、ホスト側の指定のポートにアクセスすると、コンテナ側の指定したポートでリクエストを送ることができます。 - また、
-p
オプションで、ホスト側ポートを指定しなかった場合、どのポートにアクセスするば良いのか調べる方法もあります。
$ docker container run -d -p 8080 example_go/echo:latest
2bdfce9e69c6b1ed81a7d6ea0e493e0867effa233d3f89aa8e27a793e1f29f90
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
2bdfce9e69c6 example_go/echo:latest "go run /echo_test/m…" 3 seconds ago Up 2 seconds 0.0.0.0:32769->8080/tcp elated_roentgen
- PORTSに記載されている、
0.0.0.0:32769
がホスト側のポートになります。この場合、localhost:32769
にアクセスすると、Hello Docker!!
と表示されます。
4.コンテナを操作する
コンテナで任意のコマンドを実行する
# docker container exec [options] コンテナIDまたはコンテナ名 実行するコマンド
# 今回は例として、先ほど実行したコンテナに入ります。
docker container exec -it 2bdfce9e69c6 bash
root@2bdfce9e69c6:/go#
root@2bdfce9e69c6:/go# pwd
/go
root@2bdfce9e69c6:/go#
-
docker container exec
コマンドは実行しているDockerコンテナの中で任意のコマンドを実行できます。 - 標準入力を開いたままにする
-i
オプションと仮想ターミナルを割り当てる-t
オプションを組み合わせて、対話的にシェルコマンド(bash)を実行しています。 - コンテナの中に入るときは
-it
をつけると覚えておくと便利です。
コンテナとホスト間でファイルのコピーをする
# docker container cp [options] コンテナIDまたはコンテナ名:コンテナ内のコピー元 ホストのコピー先
# コンテナ内の/echo_test/main.go を ホストの ~/以下にコピー
docker container cp 2bdfce9e69c6:/echo_test/main.go ~/
# docker container cp [options] ホストのコピー元 コンテナIDまたはコンテナ名:コンテナ内のコピー先
# ホストの ~/.ssh/id_rsa をコンテナ内の/echo_test以下にコピー
docker container cp ~/.ssh/id_rsa 2bdfce9e69c6:/echo_test
- 上記のように
cp
コマンドでコンテナとホスト間でファイルのコピーができます。 - 例にあるように、ホストssh_keyをコンテナにコピーして、コンテナからGitHubのリポジトリにアクセスするなども可能です。
5.コンテナの停止と開始、再起動と削除
- 先ほど使用した、
docker container ls
コマンドでコンテナのIDやコンテナ名を確認することができます。 - 確認したコンテナIDやコンテナ名を引数にして下記のコマンドを実行することで、コンテナの停止と開始、再起動と削除ができます。
- コンテナの停止
docker container stop コンテナIDまたはコンテナ名
- コンテナの開始
docker container start コンテナIDまたはコンテナ名
- コンテナの再起動
docker container restart コンテナIDまたはコンテナ名
- コンテナの削除
- コンテナの削除はコンテナが停止している状態でないと基本的には実行できません。
- ただ
docker rm -f コンテナIDまたはコンテナ名
のように、-f
オプションで強制削除することもできます。
docker container rm コンテナIDまたはコンテナ名
6.イメージの削除
-
docker image ls
またはdocker images
コマンドでイメージの一覧を確認できます。 - そこで表示された対象のイメージのIDを引数に指定することで、イメージを削除します。
docker image rm イメージID
# または
docker rmi イメージID
最後に
- dockerfileだけでも簡単に環境構築ができます。
- 他にも便利なコマンドがありますので、公式ドキュメントや、
docker help
コマンドで確認できます。 - ComposeやSwarm、Kubernetesなどについても、まとめていきます。