【golang】DockerでGo言語を導入してみた
はじめに
今回は、Dockerを用いてGo言語を導入する方法について紹介します。
私の動作環境
- Docker Desktop 4.21.1 (114176)
- Docker Engine 24.0.2
- Docker Compose v2.19.1
- MacOS Sonoma 14.4.1
経緯(というほどのものでもないですが)
Dockerの練習がてら、何か環境を試してみたいなぁ⋯
せや!Go言語って有名だけど使ったことないし試してみるか!
もっと使い慣れた言語で試すべきでした。
Go言語を扱う①
Dockerコンテナを使えば、プログラミング言語の環境を手軽に試せます。コンテナを破棄してしまえば、元の状態にすぐに戻せますしね。
1. ソースコードを用意する
私はカレントディレクトリに、以下のような「hello.go」というソースコードを用意しました。
package main
import "fmt"
func main(){
fmt.Printf("Hello World\n")
}
このプログラムは実行すると、画面に「Hello World」と表示するようになっています。
2. Go言語のコンテナを起動して実行する
Go言語のイメージは、「golang」という名前です。下記のサイトに使い方が記述されています。
記載されている使い方の通り(2024年5月時点)に次のコマンドを入力して実行してみます。
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:1.22 go build -v
ここで指定したオプションは、次の通りです。
--rm
実行が完了した時に、このコンテナを破棄するオプションです。
-v "$PWD":/usr/src/myapp
カレントディレクトリを、コンテナ内の/usr/src/myappに割り当てる役割を持っています。
-w /usr/src/myapp
「-w」オプションは、コンテナ内のプログラムを実行する時の作業ディレクトリを指定します。/usr/src/myappは、vオプションでマウントしたディレクトリです。これはDockerホストのカレントディレクトリにマウントされているため、コンテナ内ではこのディレクトリに対してGo言語のビルドが実行されます。
ところが、コンテナを起動することができませんでした。エラーの内容を見ると、go.modファイルが存在しないと出ています。
go.modについて説明している公式サイトによると、どうやら、go.modファイルはGo言語の依存関係を管理するために必要であるようです。
調べてみるとGo言語の公式サイトに解決方法が記載されていました。
go mod init
コマンドを使用することで、go.modファイルを作成できるようです。
go mod init
コマンドは、
go mod init プロジェクト名
といった書式で使用できます。
ではこれをコンテナの中で使用しましょう。コンテナの中をメンテナンスするためには「-it」オプションをつければ良いので、それを付けてシェルで操作できるようにして実行してみます。
docker run --rm -it -v "$(pwd)":/go/src/app -w /go/src/app golang /bin/bash
内部を操作できるようになったら、以下のコマンドを実行してgo.modファイルを作成します。
go mod init myapp
また、今回はコンパイルもコンテナ内で行う必要があるため、以下のコマンドを実行してコンパイルしましょう。
go build -o myapp .
ここで指定したオプションは、次の通りです。
go build
Go言語のコンパイラで、Goのソースコードをバイナリ実行ファイルに変換します。
-o myapp
-oオプションは、出力ファイルの名前を指定します。ここではmyappという名前の実行可能ファイルを指定しています。
.
ビルド対象を指定します。この場合、カレントディレクトリ内にある全てのGo言語のソースコードを対象としています。
ここで./myapp
と入力すると実行できます。
./myapp
実行すると、画面には「Hello World
」と表示されます。
作業が終わった後にはexit
でシェルを終了させるのも忘れずに。
exit
実際の作業画面
「--rm」オプションをつけているため、コンテナは終了した際に破棄されます。docker ps -a
で確認すると、コンテナが存在しないことがわかります。
実行環境確認
先ほどの手順でGoのソースコードを実行できました。
上記の作業を行うと、カレントディレクトリにmyapp
という名前の実行可能ファイルとgo.mod
ファイルが作成されます。
ここで注意しなければならないのは、コンテナ内で作成した実行可能ファイルはコンテナの環境で実行できるように作られているため、同じ環境を再現しなければ実行することができないということです。
手元で実行するとフォーマットが違うというエラーが出るが、コンテナ内の環境であれば実行できる
試しにfileコマンドでmyappのファイルタイプを判定してみると、以下のようになりました。
ここで、「ELF」と出力されています。これはLinux環境で実行可能な形式であり、今回作成したmyappがmacOS環境で実行できなかった理由が判明しました。
Go言語を扱う②
先ほどの実行方法では、せっかくコンテナ内で環境を構築するといったことをしているのに、手元にmyapp
やgo.mod
ファイルが残ってしまいます。
ファイルを作成せずにもっとより簡単にGoソースコードを実行する方法がないか調べていると、「go run
は指定されたメインGoパッケージをコンパイルして実行するが、go build
は指定されたパッケージとその依存関係をコンパイルする」という記述を見つけました。
つまり、go build
ではなくgo run
を使用すれば、依存関係を管理する役割を持つgo.modファイルを作成する必要がないようです。また、実行のためのコマンドを入力する手間も省けて一石二鳥です。
試しに以下のコマンドを実行してみました。このコマンドは、指定したGoのソースコード(先ほど用意したhello.go)を、golang:1.22イメージ内で実行するようになっています。
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:1.22 go run hello.go
実行すると、画面に「Hello World
」と表示され、手元にmyapp
やgo.mod
ファイルが残るようなこともありませんでした。
結論
DockerでGo言語を扱う際には、以下のように実行する方法が存在するということがわかりました。
docker run --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang go run [実行したいgoソースコード名]
このコマンドによって、Go言語のプログラムを最新版のgolang環境で実行できます。
「--rm」オプションをつけていることによって、実行後にコンテナは破棄されます。ですが、まだイメージは残っているので、もう使用しないのであればイメージを削除することも忘れないようにしましょう。
さいごに
ここまで記事を読んでくださり、ありがとうございました!
今回は、DockerでGo言語を導入してみました。Dockerを利用すれば、環境を手軽に試すことができます。この記事で紹介した方法以外にもGo言語を扱う方法は存在しているので、環境や用途に合わせて自身に合った方法を選択しましょう。
皆さんも素敵なハッピーDockerライフを!!!🌸
Discussion