個人的な備忘録：Go言語用のDockerfile周りをシェルスクリプトで一括作成した検証内容をアウトプットしてみた

## はじめに

最近、受講中のITスクールでハッカソンに参加したことをきっかけに、Googleが開発したGo言語に積極的に触れていこうと思っています。

その中で、AWSのコンテナ関連サービスであるECSやECRを使用してデプロイの検証を行いましたが、Dockerfileの作成などに少し手間取る場面がありました。

:::note info
***そこで、これらの作業を効率化するため、一括処理が可能なシェルスクリプトを作成しました。***
:::

今回の内容は、ほとんどが自分用の備忘録としてのまとめになります。***その点について、あらかじめご了承いただければ幸いです。***

## 書こうと思ったきっかけ
ローカル環境でGo言語を使って簡単な "Hello, World!" を実装していた際に、これをAWS上のECSやECRにデプロイしてみようと思い、技術検証を始めました。

https://github.com/free-honda/Go-Test

その過程で少しつまずいた部分があったため、自分でDockerfileやGo言語関連のファイルを作成して検証を行いました。***今回は、その技術検証の内容をまとめたものになります。***

## 作成するプロジェクト
今回のシェルスクリプトでは、以下のような簡単な "Hello, World!" を実現するための、最低限の構成を作成します。

```css
hello-world/
├── Dockerfile
├── go.mod
├── go.sum
└── main.go
```

## 実際に使用したコードについて
このスクリプトを実行すると、`main.go`、`Dockerfile`、`go.mod` が作成され、`go.sum` は自動的に生成されます。

***それぞれのファイルの詳細については、後述します！***

```setup.sh
#!/bin/bash

# プロジェクト名
PROJECT_NAME="hello-world"

# 作業ディレクトリ作成
mkdir -p $PROJECT_NAME
cd $PROJECT_NAME

# main.go 作成
cat <<EOF > main.go
package main

import (
	"net/http"

	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()

	// "Hello, World!" を返すハンドラー
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})

	// サーバーを起動 (外部アクセス用に 0.0.0.0 にバインド)
	e.Logger.Fatal(e.Start("0.0.0.0:1323"))
}
EOF

# Dockerfile 作成
cat <<EOF > Dockerfile
# ベースイメージ
FROM golang:1.19-alpine

# 作業ディレクトリを設定
WORKDIR /usr/src/app

# モジュール依存関係をキャッシュ
COPY go.mod go.sum ./
RUN go mod download

# アプリケーションコードをコピー
COPY . .

# アプリケーションをビルド
RUN go build -o app

# コンテナ実行時のエントリーポイント
CMD ["./app"]
EOF

# go.mod 作成
cat <<EOF > go.mod
module hello-world

go 1.19

require github.com/labstack/echo/v4 v4.10.0
EOF

# Go モジュール依存関係を解決
go mod tidy

# 成功メッセージ
echo "プロジェクト $PROJECT_NAME が作成されました。"
```

## 実行方法
シェルスクリプトを作成 上記のコードを setup.sh という名前のファイルに保存します。

### 1. シェルスクリプトの作成

上記のコードを `setup.sh` という名前で保存します。

```bash
chmod +x setup.sh
```

### 2. スクリプトに実行権限を付与

以下のコマンドを実行して、スクリプトに実行権限を付与します。

```bash
./setup.sh
```

### 3. スクリプトを実行
スクリプトを実行してプロジェクトを作成します。

```bash
./setup.sh
```

## それぞれのファイルの中身について

### main.goについて

このコードは、Echoフレームワークを使用して "Hello, World!" を返すシンプルなHTTPサーバーを構築するものです。

```main.go
package main

import (
	"net/http"

	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()

	// "Hello, World!" を返すハンドラー
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})

	// サーバーを起動 (外部アクセス用に 0.0.0.0 にバインド)
	e.Logger.Fatal(e.Start("0.0.0.0:1323"))
}
```

### Dockerfileについて

この `Dockerfile` は、Go アプリケーションをビルドし、軽量なコンテナ環境で実行するための構成を記述しています。

```Dockerfile
# ベースイメージ
FROM golang:1.19-alpine

# 作業ディレクトリを設定
WORKDIR /usr/src/app

# モジュール依存関係をキャッシュ
COPY go.mod go.sum ./
RUN go mod download

# アプリケーションコードをコピー
COPY . .

# アプリケーションをビルド
RUN go build -o app

# コンテナ実行時のエントリーポイント
CMD ["./app"]
```

### go.modについて 

```go.mod
module hello-world

go 1.19

require github.com/labstack/echo/v4 v4.10.0

require (
	github.com/labstack/gommon v0.4.0 // indirect
	github.com/mattn/go-colorable v0.1.13 // indirect
	github.com/mattn/go-isatty v0.0.16 // indirect
	github.com/valyala/bytebufferpool v1.0.0 // indirect
	github.com/valyala/fasttemplate v1.2.2 // indirect
	golang.org/x/crypto v0.2.0 // indirect
	golang.org/x/net v0.4.0 // indirect
	golang.org/x/sys v0.3.0 // indirect
	golang.org/x/text v0.5.0 // indirect
)
```

この go.mod ファイルは、プロジェクトのモジュール情報と依存関係を管理するためのファイルです。

***間接的な依存関係は、主にEchoフレームワークに必要なライブラリが含まれています。***

## まとめ
ここまでお読みいただき、ありがとうございました。今回は、少し面倒だと感じた作業をシェルスクリプトで自動化した内容をご紹介しました。

:::note warn
***次回は、このスクリプトを実際にローカル環境で動かしてみる予定です。***
:::

こうした基礎的な内容を継続的にアウトプットすることで、自分の知識を深めるだけでなく、必要なときに振り返るための良いきっかけを作りたいと考えています。


**この記事が少しでも皆さんの参考になれば幸いです！**