見出し画像

【Go初学】Dockerを使った最もシンプルなgolangアプリケーション[1]

■概要

Dockerを使った最もシンプルなgolangアプリケーションの作成について調べつつ書いていきたい。簡単なgolangを記述し、Dockerイメージの作成、コンテナの実行を行う。今回はDockerfileの作成まで。
※Dockerのインストールなどは割愛する。

▼golangアプリの作成

コンソールにログを出すだけの何の価値も生まないアプリケーションを作成する。

まず go.mod ファイルを作成し、モジュールの基点とする。

$ go mod init <モジュール名>
 
// 例
$ go mod init github.com/ArtefactGitHub/Go_T_MinimumDockerSample

main.goに処理を記述する。

package main

import (
	"fmt"
	"net/http"
)

func main() {
	fmt.Println("Hello world")

	router := http.NewServeMux()
	router.HandleFunc("/", Home)

	http.ListenAndServe(":8080", router)
}

func Home(w http.ResponseWriter, r *http.Request) {
	fmt.Println("home")
}

上記内容を実行すると、「Hello World」が出力される。

$ go run .
Hello world

Chromeなどブラウザを立ち上げ、URLに「http://localhost:8080」と入力すると、HandleFunc() で渡したハンドラー関数が呼び出され、コンソールに「home」と表示されることが確認できる。

ディレクトリ構成は下記のようなものになる。

// ディレクトリ構成
├── .dockerignore
├── .gitignore
├── go.mod
├── LICENSE
├── main.go
└── README.md


▼Dockerfileの作成

# syntax=docker/dockerfile:1

FROM golang:1.16-alpine

WORKDIR /app

COPY go.mod ./
# COPY go.sum ./
RUN go mod download

COPY *.go ./

RUN go build -o /main

EXPOSE 8080

CMD [ "/main" ]

syntax
Dockerfile構文解析のバージョン指定などを行う。
「# syntax=docker/dockerfile:1」の記述はDockerfile構築時に使うDockerfile 構文syntaxバージョン指定であり、公式で上記のバージョニング記述が推奨されている。この指定は常にバージョン 1 構文の最新安定版リリースを示しており、バージョン 1 のリリース・サイクルにおける「マイナー」と「パッチ」更新の両方を受け取ることができる。

FROM
DockerHubなどのDockerイメージレジストリにあるDockerイメージの指定。
「FROM golang:1.16-alpine」はgolangイメージのバージョン指定となる。Dockerfile命令の記述としては先頭に記述する。
1つのDockerfileで複数のイメージを作成する場合や、中間イメージとして生成したものを利用して別イメージを作成する場合は、複数のFROM命令を記述する。その際、記述したFROM行以前の状態はクリアされる。

WORKDIR
「CMD」など別命令で用いる作業ディレクトリ変数。
「WORKDIR /app」はルートディレクトリ下のappディレクトリを作業ディレクトリとして指定している。存在しない場合は作成される。
相対パス指定を行うと、現在のWORKDIRからの相対パスを表し、上記の指定に続けて「WORKDIR temp」と記述すると、「/app/temp」を示す指定となる。また「ENV」命令で設定済みの環境変数を割り当てることもできる。

COPY
1つ目の引数<コピー元>から2つ目の引数<コピー先>へコピーを行う。
「COPY go.mod ./」はローカル上のDockerfileと同一階層にある「go.mod」ファイルを、コンテナファイルシステム上の「./」にコピーする指定となる。1行コメントアウトしているのは、このアプリは何も外部パッケージを参照しておらず「go.sum」が存在しないため。
パスは、コピー元はDockerfile配置階層からのパス、コピー先はDockerイメージファイルシステム上のものになる。絶対パス、相対パスのどちらの指定も可能。指定にはfilePath.Match()のルールが適用され、「*」や「?」を使った複数のファイルマッチが可能となる("COPY hom?.txt /mydir/"など)。

RUN
「シェル形式」「実行形式」の2種類の記述があり、記述した命令
をイメージ構築時に実行する

「RUN go build -o /main」はgolangのビルドコマンドである「go build」を、「-o」オプションで出力ファイル名指定して実行する指定となる。
apt-getなどの環境アップデートが必要な際に有効なものとしてキャッシュする働きがあり、RUN実行時に処理内容がキャッシュされ、次回以降の構築時にキャッシュが利用される。

EXPOSE
"コンテナの実行時、指定した ネットワーク・ポートnetwork port をコンテナがリッスンするように、Docker へ通知するのが EXPOSE 命令です。"
「EXPOSE 8080」はコンテナ上の8080ポートで通信を待ち受ける指定となる。
ただしこの指定で実際に機能はせず、あくまでイメージの意図としてのドキュメントになる。実際にポートを公開するには、コンテナ実行コマンドの
「docker run」で「-p」フラグを使い、公開用のポートと割り当てるポート指定を行う必要がある。

CMD
"CMD の主な目的は、コンテナ実行時のデフォルト(初期設定)を指定するためです。CMD 命令は Dockerfile 中で1度しか使えません。複数の CMD 命令があれば、最後の CMD のみ有効です。"
CMD命令は3種類の構文がある。
  ▼CMD ["パラメータ1", "パラメータ2"]
 → ENTRYPOINT命令に対するデフォルトのパラメータとして扱う。
  ▼CMD ["実行ファイル","パラメータ1","パラメータ2"]
  → コンテナ実行時の実行命令(exec形式)。ENTRYPOINT命令があれば
  その全要素の続きに記述したものと同等になる。
  ▼CMD コマンド パラメータ1 パラメータ2
 → コンテナ実行時の実行命令(シェル形式)。ENTRYPOINT命令が
  あればその全要素の続きに記述したものと同等になる。
上述の「CMD [ "/main" ]」は2つ目のexec形式指定で、「RUN」でビルド出力した「main」を指定指定実行している。

(GitHub: minimumブランチ)。

■あとがき

調べつつ書いていたらこの段階で数時間経ってしまったのでここまで。echoも何も入れないとにかく最小限のgolangアプリのサンプルが見当たらなかったので着手してみた。目に見える成果物は無いが、syntax構文やEXPOSEの挙動、CMDの用途などよく分かっていなかったので収穫。

この記事が気に入ったらサポートをしてみませんか?