まえがき
goのプログラムをdockerで動かしたい、あわよくばk8sでデプロイしたいシリーズ第二弾です。
この part1 では、 docker run
してdocker上でプログラムを動作させるところまでを扱います。
流行りのdockerですが、なかなか波に乗り切れず、ローカル開発環境の方が簡単じゃない? と思ってしまっているうちにだいぶ時間が経ってしまいました。
これ以上化石になってしまわないように、なんとかdockerに入門したい。あわよくばgoを動かしたい。そんな記事です。
なお、先々にk8sでのデプロイを目論んでいる関係もあり、この記事ではdocker-compose1を扱いません。
想定読者
- dockerよくわからない
- docker使いたい
- 急に複雑な構成が出てきても困る
- オプションとかの細かい説明や「これが最強だ」みたいなハイテクコマンドが出てくると理解を拒否してしまう
- ローカル環境やVagrantでなら非常に初歩的なことで躓いてdocker入門しきれてない
- 環境構築的には、Vagrantfile(そこまで深くはわからんけど)いじったことあるよーぐらいのレベルの人
あまり想定していない読者
- docker-composeの使い方を学びたい
- docker-composeに限りませんが、しっかり学びたい方はこの記事とかすごいです いまさらDockerに入門したので分かりやすくまとめます
- goの最低限の動かし方を知りたい
- 第一弾の記事を前提にこの記事では説明を進めるので、記事内でのgoに関する説明はあまりありません
- webサーバーとか仮想環境とかなんのことだかよくわからない、ぐらいのレベルの人
- ローカルwebサーバーとしてのdockerの立ち上げ方の説明を試みているので、そのあたりの前提になっている知識の説明が少ない可能性があります。
- Windowsの方
- 筆者がMacを使っていてMacの環境を前提に説明するので、Windowsの方に全然優しくない説明の可能性が高いです
dockerの特徴について
以下のような特徴があり、旧来の勢力であるローカル開発環境やVagrantのいいとこ取りがしやすいとのことで、近年急激に普及してきています。
- 配布可能な仮想環境
- DockerfileによってIac(Infrastructure as Code)が実現でき、共通の開発環境を簡単に配布できます
- コンテナ型仮想化
- Kubernetes(通称k8s)などのコンテナオーケストレーションサービスとの連携
- 連携しやすかったです(感想)。GKEでは作ったコンテナをCloud Registryに追加して画面ぽちぽちするだけでデプロイできました。
- よりスケーラブルな話はまたいつか
以下の記事の方がよりわかりやすかったり、詳しかったりしそうです。
さて、入門以前に入っていきましょう。
動かすまでの手順というイメージです。
dockerをインストールする
docker公式サイトからインストールしてきましょう。
右上のGet Startedから、Get Started with Dockerのページに行って、 Download for Mac
をクリックします。
DockerHubのDocker Desktop for Macというページに飛ばされるので、サインアップなどを済ませて Get Docker
しましょう。
Docker.dmg
というファイルがダウンロードできたら、展開してインストールを進めます。
しばらくGUIの指示に従ってインストールを進めると、処理が完了しdockerが使えるようになります。
terminal上で
docker -v
として、
Docker version 18.09.2, build 6247962
のような表示が出れば成功です。(インストールだけは昔からしているので、↑はちょっと古いかも)
dockerを動かす
dockerを動かすまでには、いくつかのステップがあります。
最低限以下のことがわかっていれば、dockerを試すところまではいけると思います。
- docker imageを取得する
- docker imageからコンテナを起動する
それでは早速やっていきましょう。
docker imageを取得する
以下のコマンドを打てば取得できます。
docker pull golang:1.12.3-alpine3.9
このコマンドについてもうちょっとだけ説明していきます。
まず、
docker pull image名:タグ名
とすることで、 docker registry と呼ばれる docker image が保管されている場所から docker image を取得してくることができます。
取得してきた docker image の一覧は
docker images
を実行することで確認できます。
docker imageってなに?
とはいえ docker image って何よ、という話なのですが、端的にいうと「サーバーの設計書」です。
docker は docker image があれば、 docker container と呼ばれるサーバーをセットアップし、起動することができるのです。
今回でいうと、 golang
というのが docker image の名称になります。
docker imageのタグについて
では、例にあるコマンドの 1.12.3-alpine3.9
ってなんなのでしょうか。
これはタグと呼ばれる情報で、取得するイメージのバージョンや環境などを選択できます。
1.12.3
の部分はgoのバージョンを表しています。
そのあとはモノによるのですが、今回のように追加情報が記載されていることがあります。
stretch と alpine について
golang
イメージには主だったもので stretch
系と alpine
系のタグが存在します。
タグごとに docker image を定義している Dockerfile の記載が異なるので、動作が異なります。
stretch系はdebian系のimageで、 g++, gcc, libc あたりの機能をはじめにインストールしているみたいです。純粋にgolangを動かしたい方に向いている印象です。
alpine系はlinux系のimageで、あらかじめ bash, openssl などをインストールしているため通信系の機能などを含むアプリケーションの場合は取り回しがしやすいです。簡易的にWebAPIを作りたいようなときはこちらが便利そうですね。
色々と使いやすいのもあり、今回は 1.12.3-alpine3.9
を利用します。
なお、Dockerfileのレベルで確認したい方は以下のリンクが参考になります。
docker、最初はとっつきづらいなと思っていたんですが、慣れてくるとあらゆる情報がDockerHubなどを通じて公開されているのでこういうところがとても追いかけやすいなあ、と感じました。
docker imageからコンテナを起動する
docker run image名:タグ名
で起動できます4。
このコマンドで起動され立ち上がったサーバーのことを、 dockerコンテナと呼びます。
起動時の動作に指定がない docker image の場合、上記のコマンドは成功しますがその後何も起きません。
コンテナ起動時には、パターンに応じて以下のオプションを理解しておくと良いと思います。
dockerコンテナのなかでbash等のコマンドを実行したい
bashなどのコマンドを実行したい場合、 -it オプションを用います。5
docker run -it image名:タグ名
dockerコンテナをホストマシンのディレクトリでマウントして、webサーバーとして起動したい
開発用のwebサーバーとしてdockerコンテナを起動したい場合、
- 手元のコードを反映してほしい
- ローカルマシンから localhost:8080 とかでアクセスできるサーバーとして立ち上がってほしい
というニーズがあると思います。
その実現にあたっては、ざっくり以下のことを把握しておくと良いと思います。
- -p オプションで port forwarding
- -v オプションで マウント元とマウント先の指定
- -e オプションで 環境変数の指定
- -d オプションで バックグラウンド実行
- -it オプション + image:tag の後にコマンドを記載することで、webサーバー起動コマンドの流し込み
上記を踏まえた実行時のterminalのイメージは以下のような感じ。
/path/to/host
や /path/to/docker
は仮のパスなので適宜読み替えてくださいませ。
docker run -it \ # コンテナ内部に入ってbashの操作を行う。最終行でコマンド指定
-p 8080:8080 \ # ホストマシンのポートとdockerコンテナのポートを接続する。
-v /path/to/host/go:/path/to/docker/go \ # ホストマシンのディレクトリ情報でdockerコンテナの中身をマウントする。フルパスじゃないと動かないかも
-e ENV_VARIABLE=env_value \ # 環境変数の指定
-e ENV_VARIABLE2=env_value2 \ # 環境変数を複数指定する場合は繰り返し用いる
-d \ # バックグラウンド実行
image:tag \ # 使用するdocker imageの指定。確か公式リポジトリにあるやつならdocker runするときに取ってきてくれる
go run main.go /path/to/docker/go/main.go # 実行するコマンド。 -it コマンドの初期値として与えることができる
なお、 docker run
の際にはタグ名を省略することもできますが、同じ名称のimageを複数pullしてきている場合はタグまで書いた方がわかりやすいです。
ここで起動されたサーバーのことをdocker containerと呼びます。
なお、コンテナを動かすにあたっては、こちらの記事がより参考になります。コマンドの実例集は本当にありがたい。。
起動したコンテナを使って開発や動作確認をする
動く docker run コマンドの例を書いてみます。
とりあえず動かしたい! という方は真似してみてください。
事前に、上記のdocker imageを取得しておいてください。
一旦仮定として、以下のパスにいることにしましょう。
/YOUR_USER_NAME
や testproject
は適宜読み替えをお願いします。
また、 $GOPATH は ~/go
という仮定で話を進めます。
pwd #=> /Users/YOUR_USER_NAME/go/src/github.com/testproject/
ここでいつものサンプルを作成します。
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on 0.0.0.0:8080
}
この状態で、以下のようなコマンドを実行します。
docker run -it \
-p 8080:8080 \
-v /Users/YOUR_USER_NAME/go/src/github.com/testproject:/go/src/github.com/testproject \
golang:1.12.3-alpine3.9 \
go run /go/src/github.com/testproject/main.go
これを実行すると、 docker image を元にした docker container が起動し、ローカルサーバーが立ち上がります。
localhost:8080/ping
にアクセスして、 {"message": "pong"}
のレスポンスが返ってくれば成功です。
その他のコマンドについて
以下を覚えておくと入門以前のレベルとしては十分だと思います。
docker images # 手元にある docker image が確認できる
docker rmi [IMAGE ID] # 指定したimageが削除できる。IMAGE IDは docker images で確認できる
docker ps # 起動中のコンテナが確認できる
docker kill [CONTAINER ID] # 指定したcontainerを停止できる。CONTAINER IDは docker ps で確認できる
Dockerfile使ったりdocker buildしたりしたい。そしてコンテナをデプロイしたい
そんな感じで、dockerのなんとなくの概要とかをまとめつつ、docker runでサーバーが起動するところまでを駆け足でまとめてみました。
Dockerfileってなに?
手元で動くだけじゃ困るんだけど?
みたいな悩みが本番デプロイやdocker imageの配布などを行いたい人には発生すると思うのですが、これは次回以降に続きます。続け!
-
docker-composeとは、複数のdockerコンテナ(記事内で言及予定)を構成管理できるツールです。よくセットで出てくるけどdockerに対するメタツールなので必須ではないものです。例えばWebアプリケーションサーバーとしてのコンテナと、MySQLサーバーとしてのコンテナを同時に立ち上げ、接続設定まで済ませるといったことが可能です。この記事ではできる限りシンプルにdockerの動かし方を学びたい(しかもこれ書いてる人もdocker-composeよくわかってない)ため、言及していません ↩
-
完全に余談ですが、シミュレートは内部の動作を再現すること、エミュレートは目に見える動作を再現することを指すらしく、位置付けがけっこう異なるようです。高度に完成されたシミュレーションとエミュレーションは同じ結果をもたらす、とも言われています。 ↩
-
IE8を再現するためのVirtualBoxイメージとかね・・・ ↩
-
Vagrantでの
vagrant up
にあたります ↩ -
Vagrantでの
vagrant up → vagrant ssh
にあたります ↩