Go でのビルドとパッケージング


Go でのビルドとパッケージングの基礎



パッケージングは​​、おそらくコード自体を書くことと同じくらい重要です.大量のラテン語コマンドを含む Makefile とその Makefile を使用する DockerFile を使用する Go プロジェクトを見て、私のように混乱した場合は、これが役立つかもしれません.

Go ファイルのビルド



Go を初めて使用する場合は、 go run を使用して Go アプリケーションを実行している可能性があります. .これは、本番環境で実行したり、ローカル以外の場所で実行したりするための推奨される方法ではありません.後で実行できる実行可能ファイルを作成する go build を使用してアプリケーションをビルドする必要があります. *通常、これらすべてを行うために Makefile が使用されます. 「make」は Makefile を実行するプログラムです. *「make」はビルドを効率的に処理します. 「make」を使用すると、最後のビルド以降に変更されたファイルと、変更されたファイルに依存するファイルのみがコンパイルされるようにすることができます. 「make」は、ファイルのタイムスタンプを使用して、ファイルが変更されているかどうか、および再コンパイルする必要があるかどうかを確認します.

私のプロジェクトのメイクファイルは次のようになりました (説明の後に # が続きます):

CLI で make または make all を実行すると、app1exec と app2exec の 2 つの実行可能ファイルが現在の作業ディレクトリに作成されます.

PWD := $(shell pwd) #variable declarations
GOPATH := $(shell go env GOPATH)
source := $(wildcard *.go **/*.go */*/*.go)
IMAGES:=imageapp1 imageapp2
OTHER_FLAGS:=-tags musl

all: app1 app2 #these targets are run if you run `make` or `make #all` from the CLI

deps:  #dependencies I'm downloading gobin and a linter here
@GO111MODULE=off go get -u github.com/myitcv/gobin
@$(GOPATH)/bin/gobin github.com/golangci/golangci-lint/cmd/[email protected]

test: #all tests are run if I run `make run` on the CLI
go test ./...

build: #this is more like a check whether everything can be built #because go build ./... discards the results after running
go build ./...

run: #to run locally
go run github.com/shashankks0987/app1 & \
go run github.com/shashankks0987/app2

app1: $(source)  #the $(source) tells Makefile the dependent #project directories. If no file has changed in these, it will not 
#run this job
@echo "Building app1 to $(PWD)/app1..."
@CGO_ENABLED=1 GO111MODULE=on go build $(OTHER_FLAGS) -o app1exec github.com/shashankks0987/app1

app2: $(source)
@echo "Building app2 to $(PWD)/app2..."
@CGO_ENABLED=1 GO111MODULE=on go build $(OTHER_FLAGS) -o app2exec github.com/shashankks0987/app2

docker:  #this is what you'll use to dockerize your code 
@echo "Making docker image"

for image in $(IMAGES); do\
echo $$image;\
docker build . --target $$image -t $$image;\
done

CGO_ENABLED=1 を指定すると、ビルド OS での実行時に、ホスト OS のネイティブ ライブラリ (glibc、DNS リゾルバーなど) を動的にロードできるため、ビルドとランタイムが高速で小さくなります.これは、ローカルの迅速な開発に最適です.
これは、有効にするかどうかを決定するのに適しています.

コードを配布するには、バイナリ、実行可能ファイル、Docker イメージなど、さまざまな方法があります. docker イメージを使用すると、OS やその他のシステムの仕様に関係なくコードが同じように実行されるようになるため、最も用途が広い場合があります.

この DockerFile からいくつかのアイデアを引き出すことができますが、プロジェクトに最適なものを知っておく必要があります.

FROM golang:1.17-alpine AS build_base
RUN apk add make git gcc musl-dev

コンテナ内に現在の作業ディレクトリを設定する

WORKDIR /tmp/app
COPY go.mod ./go.mod
RUN go mod download
COPY . .
RUN make deps
RUN make

FROM alpine:3.9 as app1
LABEL name=app1
RUN apk add ca-certificates
COPY --from=build_base /tmp/app/app1exec /app/app1
RUN adduser -D -H -u 1801 user1
USER 1801
CMD ["/app/app1"]

FROM alpine:3.9 as app2
LABEL name=app2
RUN apk add ca-certificates
COPY --from=build_base /tmp/app/app2exec /app/app2
RUN adduser -D -H -u 1801 user1
USER 1801
CMD ["/app/app2"]


資源 上記の DockerFile で何が起こっているか:



1) ソース コードをコピーし、依存関係をダウンロードし、makefile を使用して必要な実行可能ファイルを作成するベース コンテナーを構築します.

2) 続く他の 2 つのイメージは、基本イメージから実行可能ファイルをコピーするだけです.

3) app1 と app2 がドッキングされ、実行する準備が整いました!

この記事を読んで、Go でファイルをビルドしてパッケージ化する方法について公正なアイデアを得ることができ、次にコードベースでこれらのファイルを目にしたときに (私がしたように) パニックにならないことを願っています.