LoginSignup
2
2

More than 1 year has passed since last update.

go開発環境をDockerで作成する①

Last updated at Posted at 2022-06-04

最終目的

go言語でWebアプリを構築するためのgo開発環境をDockerで作成する。

目標

goの選定

現在(2022/06/04)、最新のgoは1.18.3。

1.17と1.18で大きな仕様変更(Genericsの導入、Fuzzingが標準機能)あり。今までのアップグレードに比べて最大の変更ではないか?
Genericsは1.19で正式になり、1.18では試験的実装とのこと。
安定している1.17にしようかと思っていたが、勉強のためなので最新の1.18にして、Genericsを使用し始めよう。
なので、1.18系とする。

dockerイメージの選定

クラウド上にDeployすることを考えると、linux環境になる。destributionを考える。開発中にいろいろやりたいとするとubuntu。

ubuntuのLTSベースとしたかったが、ubuntuベースのgolangイメージなし...
DebianはイメージがあるのでDebianにする。

DebianのCurrent LTSはStretchだが、6/30で切れる...
次は、Debian 10 “Buster” で2024年6月まで。busterにしよう。

golangのバージョンは固定にして、必要なタイミングでマイナー(3桁目)をアップグレードしよう。
イメージは、1.18.3-busterとする。

イメージ落としたらサイズがでかい。Deployの環境はalpineにするか別途検討。

Dokerfileの作成

クラウドにDeployする時のDockerfileと開発環境用のDockerfileは分けたい。
makeコマンドで立ち上げができるようにenvディレクトリにDockerfileをまとめる。

./
+ env/
  + Dockerfile.golang.dev

env/Dockerfile.golang.dev作成

Dockerfile.golang.dev
FROM golang:1.18.3-buster

試しにDockerイメージ作成、bashを立ち上げてみて、環境を確認。

Dokerfileの動作確認
$ docker build -f env/Dockerfile.golang.dev -t dev-env-golang:latest .
$ docker run --rm -it golang-dev bash

root@48a707dd66d1:/go# uname -a
Linux 48a707dd66d1 5.10.102.1-microsoft-standard-WSL2 #1 SMP Wed Mar 2 00:30:59 UTC 2022 x86_64 GNU/Linux

root@48a707dd66d1:/go# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

root@48a707dd66d1:/go# hostname
48a707dd66d1

root@48a707dd66d1:/go# ip -4 address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
15: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default  link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

root@48a707dd66d1:/go# ip -4 route
default via 172.17.0.1 dev eth0
172.17.0.0/16 dev eth0 proto kernel scope link src 172.17.0.2

root@48a707dd66d1:/go# go version
go version go1.18.3 linux/amd64
  • goは1.18.3
  • distributionはDebian 10 buster
  • rootでアクセス
  • ホスト名、IPアドレスはdocker runごとに変わる
  • ネットワークIPはdocker設定のIP(作業者で異なる可能性)

rootアクセスはやめたい、ホスト環境のディレクトリをコンテナ環境のホームディレクトリに割り当てたい、ネットワークアドレスを指定したい、立ち上げをmakeコマンドで実施したい。

docker-composeとMakefileで制御することにする。

docker-compose環境の作成

方針

  • ネットワークアドレスを指定したい
  • rootアクセスはやめてgouserユーザーアクセス
  • src/golangディレクトリをコンテナ環境の/home/gouserに割り当てる
  • 環境設定はファイルで設定(環境設定はコード管理しない)
  • makeコマンドでいろいろ操作(長いコマンド打ちたくない)

構成は下記

./
+ env/
|   + Dockerfile.golang.dev
+ src/
|   + golang/
|      + <home dir>
+ docker-compose.dev.yml
+ Makefile
+ .env           # 環境変数(コード管理外)
+ .env.dev       # コンテナ実行時の共通環境変数

ネットワークIPを固定化

dockerコマンドでコンテナが使用するネットワークdev-env-linkを作成する。

  • コンテナからinternetにアクセスできる
  • ネットワークアドレスは192.168.10.0/24
  • gatewayは192.168.10.254 (コンテナのIPは1から振りたい)

docker-compose環境を複数立てたときに同一ネットワーク環境に同居させたいので、docker-compose.ymlでネットワークを定義しない。

docker networkの作成
$ docker network create --driver=bridge \
  --subnet=192.168.10.0/24 \
  --gateway=192.168.10.254 \
  env-link

ネットワーク削除は下記

docker networkの破棄
docker network remove dev-env-link

コマンド類は後でMakefileで定義する。

docker-compose.dev.ymlの作成

開発環境の各種設定は.envファイルで管理して、docker-compose.ymlで読み込み、Dockerイメージ作成時に継承させる。
.envファイルはコード管理外にする。

.env
NETWORK_BASE=192.168.10
NETWORK_ADDR=192.168.10.0/24
NETWORK_GATEWAY_IP=192.168.10.254
TZ=Asia/Tokyo

USER_NAME=gouser

USER_ID=1000
GROUP_NAME=gouser
GROUP_ID=1000

コード管理してよい環境変数設定は.env.devで管理する。

.env.dev
LANGUAGE=C
LANG=C.UTF-8
LC_ALL=C.UTF-8

docker-compose.dev.ymlを作成

docker-compose.dev.yml
version: "3"
services:
  golang:
    build:
      context: .
      dockerfile: ./env/Dockerfile.golang.dev
      args:
        - USER_NAME=$USER_NAME
        # - USER_PW=$USER_PW # いらない
        - USER_ID=$USER_ID
        - GROUP_NAME=$GROUP_NAME
        - GROUP_ID=$GROUP_ID
        - TZ=$TZ
    image: dev-env-golang-image
    container_name: dev-env-golang
    command: bash
    tty: true
    volumes:
      - ./src/golang:/home/$USER_NAME
    env_file: .env.dev
    environment:
      - GO111MODULE=on
    networks:
      dev-env-link:
        ipv4_address: $NETWORK_BASE.1    # .envのNETWORK_BASEと合わせて、コンテナのIPは192.168.10.1になる

networks:
  dev-env-link:
    external: true

Dockerfaleの書き換え

docker-compose.ymlからの環境変数を使用して以下の設定を行うように書き換える。

  • logaletimeの設定
  • システムユーザーの作成
Dockerfile.golang.dev
FROM golang:1.18.3-buster

ARG USER_NAME=$USER_NAME
ARG USER_ID=$USER_ID
ARG GROUP_NAME=$GROUP_NAME
ARG GROUP_ID=$GROUP_ID
# ARG USER_PW=$USER_PW # いらない
ARG TZ=$TZ
ENV TZ=$TZ

RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime

ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y sudo

RUN groupadd -g $GROUP_ID $GROUP_NAME && \
    useradd -s /bin/bash -u $USER_ID -g $GROUP_ID -G sudo $USER_NAME -r -d /home/$USER_NAME -M && \
    # パスワード設定いらない    
    # echo $USER_NAME:$USER_PW | chpasswd && \
    echo "$USER_NAME   ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

USER $USER_NAME
WORKDIR /home/$USER_NAME

docker-composeでbuild、up、execを実施。runで立ち上げないのは、stopでコンテナを止めたい、同一コンテナ上で複数のコンソールを立ち上げたいため。

docker-composeでの環境立ち上げ確認
$ docker-compose -f docker-compose.dev.yml build --force golang
$ docker-compose -f docker-compose.dev.yml up -d golang
Creating dev-env-golang ... done
$ docker-compose -f docker-compose.dev.yml exec golang bash
gouser@e0dd620928c2:~$

gouser@e0dd620928c2:~$ ip -4 address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
173: eth0@if174: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default  link-netnsid 0
    inet 192.168.10.1/24 brd 192.168.10.255 scope global eth0
       valid_lft forever preferred_lft forever

gouser@e0dd620928c2:~$ ip -4 route
default via 192.168.10.254 dev eth0
192.168.10.0/24 dev eth0 proto kernel scope link src 192.168.10.1

gouser@e0dd620928c2:~$ grep gouser /etc/passwd
gouser:x:1000:1000::/home/gouser:/bin/bash

gouser@e0dd620928c2:~$ grep gouser /etc/group
sudo:x:27:gouser
gouser:x:1000:

gouser@e0dd620928c2:~$ export | grep -E '(LAN|LC|TZ|GO)'
declare -x GO111MODULE="on"
declare -x GOLANG_VERSION="1.18.3"
declare -x GOPATH="/go"
declare -x LANG="C.UTF-8"
declare -x LANGUAGE="C"
declare -x LC_ALL="C.UTF-8"
declare -x TZ="Asia/Tokyo"

試しに別ターミナルでdocker-compose top、execをしてみる。upで立ち上がったbashと、execで立ち上げたbashの2プロセスが起動している。もう一度execすると3つ目のbashプロセスが同一コンテナで立ち上がる。

docker-composeでの環境立ち上げ確認(別ターミナルで)
$ docker-compose -f docker-compose.dev.yml top
dev-env-golang
UID     PID    PPID    C   STIME   TTY     TIME        CMD
-------------------------------------------------------------
1000   18191   18170   0   14:20   ?     00:00:00   /bin/bash
1000   18260   18170   0   14:20   ?     00:00:00   bash

$ docker-compose -f docker-compose.dev.yml exec golang bash
gouser@e0dd620928c2:~$

Makefile作成

環境操作を簡単に操作できるようにMakefileを作っておく。

Makefile
.PHONY: \
	env-create env-destroy env-down env-rmi env-build env-top env-images \
	net-init net-deinit \
	go-build go-up go-console go-stop go-down go-rmi

# 変数 --------------------------
# network addressを.envrcから取得
NETWORK_ADDR := $(shell grep 'NETWORK_ADDR' .env | sed -r 's/NETWORK_ADDR=(.+)/\1/g' )
# gateway addressを.envrcから取得
NETWORK_GATEWAY_IP := $(shell grep 'NETWORK_GATEWAY_IP' .env | sed -r 's/NETWORK_GATEWAY_IP=(.+)/\1/g' )

# 環境 --------------------------
env-create: net-init env-build
env-destroy: env-rmi net-deinit

env-down:
	# 全コンテナ停止
	-$(DC) down

env-rmi:
	# 全コンテナ停止とイメージ削除
	-$(DC) down --rmi all

env-build: go-build

env-top:
	$(DC) top

# ネットワーク -------------------
net-init:
	-$(D) network create --driver=bridge --subnet=$(NETWORK_ADDR) --gateway=$(NETWORK_GATEWAY_IP) dev-env-link

net-deinit:
	-$(D) network remove dev-env-link

# golang環境 ---------------------
go-build:
	$(DC) build --force golang

go-up:
	$(DC) up -d golang

go-console: go-up
	$(DC) exec golang bash

go-stop:
	-$(DC) stop golang

go-down: go-stop
	-$(DC) rm -f golang

go-rmi: go-down
	-$(D) rmi -f dev-env-golang-image

ここまで。
作成した環境は GitHub を参照。

その他

この作業で便利なVSCode extension

  • Docker(Microsoft)
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2