最近Kubernetesを覚えようと触っているのですが、その前段階としてDockerの復習もしたので、軽くまとめておきます。
ローカルで構築する手順的な部分だけで、動かすこと優先でやっているので、それぞれの要素も説明とかは浅いです。
すっ飛ばしてる内容もあるので、詳細は別途調べてもらえればと思います。
参考にした資料は下記の書籍です。
gihyo.jp
Dockerで環境構築
Docker for Macのインストール
今回の手順は全てDocker for Macを使用して、Mac PCのローカル環境で実行します。
下記のサイトから、ダウンロードしてインストールしてください。
手順や確認方法も載っています。
コンテナとイメージ
Dockerで作る仮想環境は、「コンテナ」という単位で管理します。
そしてそのコンテナを作るのに、イメージというものを使います。
コンテナ・・・仮想環境 イメージ・・・コンテナを作るための設定や情報が入ったもの
みたいなイメージ。
それぞれの詳細と作り方をもうちょっと説明します。
Docker上で動かすサンプルプログラム
まず、Docker上で動かす動作確認用のサンプルプログラムとして下記を作っておきます。
(本当はKotlinでやりたいところですが、一旦手軽でサンプルも多い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 World!!") }) log.Println("started") server := &http.Server{Addr: ":8080"} if err := server.ListenAndServe(); err != nil { log.Println(err) } }
イメージの作成
まずはコンテナの元となるイメージを作成します。
Dockerfile
という名前のファイル(拡張子なし)を作成して、下記を記述してください。
FROM golang:1.9 RUN mkdir /sample COPY hello.go /sample CMD [ "go", "run", "/sample/hello.go" ]
イメージは「コンテナを作るための設定や情報が入ったもの」と前述しましたが、その設定などがDockerfileに入っています。
一行ずつ説明していくと、
FROM golang:1.9
のFROMは、作りたいイメージのベースとなるイメージを設定しています。
今回はGoを動かす環境を作りたいため、golang
というイメージを指定しています。
このイメージは、Docker Hubというところからダウンロードされます(Dockerイメージの上がっているGitHubみたいなものです)。
:の後の数字はは「タグ」と言われるもので、Gitのタグと同じようなものと考えて良いと思います。
今回は1.9
のバージョンのタグを使います。
RUN mkdir /sample COPY hello.go /sample
RUNはDockerイメージのビルド時に実行される処理です。
サンプルプログラムを配置するための「sample」というディレクトリを作成しています。
そして、COPYはホスト(ビルドを実行している端末)にあるファイルをコンテナにコピーします。
ここではビルドを実行しているディレクトリ内にある「hello.go」というファイルを先ほどRUNで作成した「sample」というコンテナ内のディレクトリにコピーします。
CMD [ "go", "run", "/sample/hello.go" ]
CMDは、Dockerコンテナを起動する時に、コンテナ内で実行する処理になります。
ここでは起動時に先ほどコピーしておいた「hello.go」を実行しています。
CMDの書き方は少し特殊で、このサンプルで言うと
go run /sample/hello.go
をスペースで区切って、分離して配列として書いているような形になります。
そして、このDockerfileを元に、Dockerイメージをビルドします。
下記のコマンドで実行できます。
ntakehata$ docker image build -t ntakehata/hello:latest .
ntakehata/hello:latest
の部分はコンテナの名前と、タグの名前(:から後ろ)になります。
.
はDockerfileの置いてある場所です。ここで指定したディレクトリからDockerfile
という名前のファイルを探して、ビルドを始めます。
下記のように表示されればビルド成功です。
Step 1/4 : FROM golang:1.9 ---> ef89ef5c42a9 Step 2/4 : RUN mkdir /sample ---> Using cache ---> 0edc47a2cdb9 Step 3/4 : COPY hello.go /sample ---> Using cache ---> 250c3984b73f Step 4/4 : CMD [ "go", "run", "/echo/hello.go" ] ---> Using cache ---> 3d6091e879fb Successfully built 3d6091e879fb Successfully tagged ntakehata/hello:latest
作られたイメージは、下記のコマンドで確認できます。
ntakehata$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE ntakehata/hello latest 3d6091e879fb 5 minutes ago 750MB
このイメージを使うことで、
①/sampleというディレクトリを作成 ②hello.goを/sampleにコピー ③hello.goを実行
した状態のコンテナを作ることができます。
前述したようにあくまでこれはイメージで、これだけでは何も動かないので、次は実際にコンテナを作ってアクセスしてみます。
Dockerコンテナの実行
下記の docker container run
というコマンドで、コンテナを起動できます。
ntakehata$ docker container run -d --name hello ntakehata/hello:latest 8d6565e76f20aefdb5e171dd21aa7e1e6c04ac885a0eb25880de5687387c5098
-d
はバックグラウンド実行、 --name
作成するコンテナ名を指定します。
コンテナ名は省略した場合は、自動でランダムな名前が付けられます。
そして、最後に先ほど作成した ntakehata/hello:latest
というイメージ名を指定しています。
これで、「ntakehata/hello:latest
のイメージを元にhello
というコンテナを作り、バックグラウンドで実行する」ことができます。
作られたコンテナは docker container ls
というコマンドで確認できます。
ntakehata$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8d6565e76f20 ntakehata/hello:latest "go run /sample/hell…" 5 seconds ago Up 4 seconds hello
このコンテナは、前述の
①/sampleというディレクトリを作成
②hello.goを/sampleにコピー
③hello.goを実行
が実行され、hello.goが起動した状態のコンテナが自分のPCの中に作られたイメージです。
ただ、コンテナは同じPC内にありながらも、あくまでも別の環境(仮装環境)という形なので、ローカル環境のように http://localhost:8080 にアクセスしても接続できません。
このアクセスをする方法を、これから説明します。
Dockerコンテナの停止
その前に、先ほど起動したコンテナを一度停止しましょう。
作ったコンテナの停止は、 docker container stop
というコマンドで、コンテナIDかコンテナ名を指定します。
ntakehata$ docker container stop 8d6565e76f20 8d6565e76f20
下記はコンテナ名で実行した例です。
docker container stop hello
ポートフォワード
さて、それではコンテナ上で起動したhello.goで立てたサーバーにアクセスする方法です。
これには「ポートフォワード」という機能を使います。
下記のコマンドで、もう一度コンテナを起動してください。
ntakehata$ docker container run -d -p 9000:8080 --name hello ntakehata/hello:latest d8b850dd4e7013ffc8af015d493c832b798c6189273f47459ced72755c4d84fb
-p 9000:8080
というオプションを追加しています。
これは「ポートフォワード」という機能を使うためのもので、この例で言うとローカル環境の9000ポートを経由して、コンテナhelloの8080へアクセスできるようになります。
:
の前が受け付けるローカル環境のポート、後が流したい先のコンテナのポートです。
下記のcurlコマンドで9000ポートにアクセスすると、コンテナ上のhello.goにアクセスできているのが分かります。
ntakehata$ curl http://localhost:9000/ Hello World!!
DockerイメージのPush
Dockerには、Docker Hubというイメージを置いて公開できるGitHubのようなサイトがあります。
こちらは必須ではないですが、もしこちらに置きたい場合は、下記のコマンドでPushできます。
ntakehata$ docker image push ntakehata/hello:latest The push refers to repository [docker.io/ntakehata/hello]
Dockerfileで指定するイメージも、こちらに置いてあるものを指定することができます(先ほどのgolangのイメージも置いてあります)。
ちなみにこのサンプルで置いている「ntakehata/hello:latest」というイメージもDocker HubにPushしてあるので、良ければ使ってみてください。
Docker Composeで複数コンテナの起動
ここまででhello.goの起動まではできました。
ただ先ほどのやり方では1コンテナずつの起動しかできないので、今度は複数コンテナを同時に起動してみます。
実際の環境構築はプログラムだけでなく、nginxやMySQLといったミドルウェアも一緒に必要になってくるのでこちらの方法を使います。
複数コンテナの起動には、Docker Composeというものを使います。
Docker Composeは簡単に言うと、 docker-compose.yml
という設定ファイルを書き、その内容に則ってコンテナを起動するものです。
まずは単一のコンテナの起動を試してみる
下記の内容で、docker-compose.ymlという名前のファイルを作ってください。
version: "3" services: hello: image: ntakehata/hello:latest ports: - 9000:8080
この設定の説明ですが、まず version
で指定しているのは使用するDocker Composeのバージョンです。
そして、 services
の下に作成するコンテナの設定を書いています。
今回は前述のコマンドラインで起動してたのと同じく、helloという名前で作成します。
helloの下の階層で書いている image
と ports
は、それぞれコンテナの元になるイメージ、ポートフォワードの設定を記述しています。
そしてファイルのあるディレクトリで、下記の docker-compose
コマンドを実行します。
ntakehata$ docker-compose up -d Creating network "docker_default" with the default driver Creating docker_hello_1 ... done
これで先ほどコマンドで起動していたコマンドと同じものが立ち上がっています。
ntakehata$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ff82f298d6d6 ntakehata/hello:latest "go run /sample/hell…" 12 seconds ago Up 11 seconds 0.0.0.0:9000->8080/tcp docker_hello_1
ちなみに名前だけ「docker」が付いたりと少し変わりますが、先ほどのコマンドラインで作成したのと同じコンテナが作られています。
Docker Composeで作成したコンテナの削除は、下記で実行します。
ntakehata$ docker-compose down Stopping docker_hello_1 ... done Removing docker_hello_1 ... done Removing network docker_default
複数コンテナを作成してみる
今度は本題で、複数コンテナを一気に作成します。
docker-compose.ymlを下記のように変更してください。
version: "3" services: hello: image: ntakehata/hello:latest ports: - 9000:8080 nginx: image: nginx:1.13.5-alpine ports: - 80:80
servicesの下に「nginx」という名前のコンテナを追加しました。
指定しているイメージはDocker Hub上にあるnginxのコンテナを作るためのイメージで、ここではローカルの80番ポートからコンテナ内の80番ポート(nginxのデフォルトポート)にポートフォワードしています。
このように、servicesの下にコンテナの設定を羅列していくことで、複数のコンテナを同時に作成、起動することができます。
作成は同じように、 docker-compose
コマンドで実行します。
(初回作成時はnginxのイメージのPullが走ると思います)
ntakehata$ docker-compose up -d Creating network "docker_default" with the default driver Creating docker_nginx_1 ... done Creating docker_hello_1 ... done
helloとnginx、2つのコンテナが起動しました。
下記でhelloの動作確認。
ntakehata$ curl http://localhost:9000 Hello World!!
そして下記で80番ポートにアクセスすると、nginxのデフォルトページが表示されると思います。
ntakehata$ curl http://localhost <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
ブラウザで http://localhost にアクセスしても、確認できると思います。
次はKubernetes
とりあえずDockerで基本的な環境を作るところまでできました。
次はこれと同等の環境をKubernetesで作っていきます。