Docker を使用して Go Web アプリケーションをデプロイする方法

Docker を使用して Go Web アプリケーションをデプロイする方法

この記事では、Docker と Docker Compose を使用して Go Web アプリケーションをデプロイする方法を紹介します。

なぜ Docker が必要なのでしょうか?

Docker を使用する主な目的はコンテナ化です。つまり、アプリケーションが実行されるホストに関係なく、アプリケーションに一貫した環境を提供します。

次のようなシナリオに遭遇したと想像してください。アプリケーションをローカルで開発しており、多くの依存環境やパッケージがあり、依存関係の特定のバージョンに厳しい要件がある可能性があります。開発プロセスが完了したら、アプリケーションを Web サーバーにデプロイする必要があります。この時点で、すべての依存関係が正しくインストールされ、まったく同じバージョンであることを確認する必要があります。そうでないと、アプリケーションがクラッシュして実行されなくなる可能性があります。アプリケーションを別の Web サーバーにデプロイする場合は、プロセスを最初から繰り返す必要があります。このシナリオでは Docker が役立ちます。

アプリケーションを実行するホストがラップトップでも Web サーバーでも、必要なのは Docker コンテナ プラットフォームを実行することだけです。これからは、MacOS、Ubuntu、Arch などのどれを使用しているかを心配する必要はありません。アプリケーションを一度定義すれば、どこでも実行できます。

Docker デプロイメントの例

コードの準備

ここでは、net/http ライブラリを使用して記述された簡単なコードを例として、Docker をデプロイメントに使用する方法を説明し、次にもう少し複雑なプロジェクト デプロイメントのケースについて説明します。

パッケージメイン

輸入 (
 「fmt」
 「ネット/http」
)

関数main() {
 http.HandleFunc("/", こんにちは)
 サーバー:= &http.Server{
 アドレス: ":8888",
 }
 fmt.Println("サーバーの起動...")
 err := server.ListenAndServe() の場合; err != nil {
 fmt.Printf("サーバーの起動に失敗しました、エラー:%v\n", err)
 }
}

関数hello(w http.ResponseWriter, _ *http.Request) {
 w.Write([]byte("こんにちはliwenzhou.com!"))
}

上記のコードは、ポート 8888 を介して外部サービスを提供して、文字列応答「hello liwenzhou.com!」を返します。

Dockerイメージの作成

イメージには、コードまたはバイナリ、ランタイム、依存関係、その他の必要なファイル システム オブジェクトなど、アプリケーションの実行に必要なものがすべて含まれています。

簡単に言えば、イメージとは、アプリケーションを定義し、実行するために必要なものすべてです。

Dockerfileの作成

Docker イメージを作成するには、構成ファイルで手順を指定する必要があります。デフォルトでは、このファイルは通常 Dockerfile と呼ばれます。 (このファイルには任意の名前を付けることができますが、デフォルトの Dockerfile を使用することをお勧めします。)

ここで Dockerfile の記述を始めます。具体的な内容は次のとおりです。

注: 一部の手順は一意ではなく、ファイル パス、最終的な実行可能ファイルの名前など、必要に応じて変更できます。

golang:alpine より

# イメージに必要な環境変数 ENV GO111MODULE=on を設定します \
 CGO_ENABLED=0 \
 GOOS=Linux \
 GOARCH=amd64

# 作業ディレクトリに移動: /build
ワークディレクトリ /build

# コードをコンテナにコピーします COPY . .

# コードをバイナリ実行ファイルアプリにコンパイルする
go build -o app を実行します。

# 生成されたバイナリファイルを保存する /dist ディレクトリに移動します WORKDIR /dist

# /build ディレクトリからバイナリ ファイルをここにコピーします。 RUN cp /build/app 。

#サービスポートをEXPOSE 8888と宣言する

# コンテナの起動時に実行するコマンド CMD ["/dist/app"]

Dockerfile の解析

から
イメージの作成にはベースイメージ golang:alpine を使用しています。これは、アクセス可能な Docker リポジトリに保存される、これから作成するベース イメージと同じです。このイメージは、サイズが小さく、Go が組み込まれている alpine Linux ディストリビューションを実行するため、私たちのユースケースに最適です。公開されているDockerイメージは多数あります。https://hub.docker.com/_/golangを参照してください。

環境
コンパイルフェーズ中に必要な環境変数を設定するために使用されます。

WORKDIR、コピー、実行
コマンドはコメントで説明されているのでわかりやすいです。

エクスポート、CMD
最後に、アプリケーションがこのポートをリッスンし、このポートを通じて外部サービスを提供するため、サービス ポートを宣言します。また、イメージを実行するときに実行されるデフォルトのコマンド CMD ["/dist/app"] も定義します。

イメージを構築する

プロジェクト ディレクトリで、次のコマンドを実行してイメージを作成し、イメージ名を goweb_app として指定します。

docker ビルド . -t goweb_app

ビルド プロセスが完了するまで待つと、次のプロンプトが出力されます。

...
90d9283286b7 の構築に成功しました
goweb_app:latest のタグ付けに成功しました

これでイメージの準備はできましたが、現時点では何も実行されません。次に必要なのは、リクエストを処理できるようにイメージを実行することです。実行中のイメージはコンテナと呼ばれます。

イメージを実行するには、次のコマンドを実行します。

docker run -p 8888:8888 goweb_app

-p フラグはポート バインディングを定義するために使用されます。コンテナ内のアプリケーションはポート 8888 で実行されているため、ホスト ポートも 8888 にバインドします。別のポートにバインドする場合は、-p $HOST_PORT:8888 を使用できます。たとえば -p 5000:8888。

これで、Web プログラムが正しく動作しているかどうかをテストできます。ブラウザを開いて http://127.0.0.1:8888 と入力すると、次のように事前に定義した応答コンテンツが表示されます。

こんにちは、liwenzhou.com!

段階的なビルドの例

Go プログラムをコンパイルすると、実行可能なバイナリ ファイルが生成されます。実際、最終イメージでは Go コンパイラは必要ありません。つまり、最終バイナリ ファイルを実行するためのコンテナーのみが必要です。

Docker のベスト プラクティスの 1 つは、バイナリ ファイルのみを保持してイメージ サイズを縮小することです。これを実現するには、マルチステージ ビルドと呼ばれる手法を使用します。これは、イメージを複数のステップでビルドすることを意味します。

golang:alpine AS ビルダーから

# イメージに必要な環境変数 ENV GO111MODULE=on を設定します \
 CGO_ENABLED=0 \
 GOOS=Linux \
 GOARCH=amd64

# 作業ディレクトリに移動: /build
ワークディレクトリ /build

# コードをコンテナにコピーします COPY . .

# コードをバイナリ実行ファイルアプリにコンパイルする
go build -o app を実行します。

###################
# 次に、小さなミラーを作成します#####################
ゼロから

# ビルダーイメージから /dist/app を現在のディレクトリにコピーします COPY --from=builder /build/app /

# 実行するコマンド ENTRYPOINT ["/app"]

この手法を使用して、ビルド イメージとして golang:alpine を使用してバイナリ実行可能ファイルをコンパイルするプロセスを削除し、スクラッチに基づいてシンプルで非常に小さな新しいイメージを生成しました。最初のイメージ「builder」から新しく作成されたスクラッチ イメージにバイナリをコピーします。スクラッチイメージの詳細については、https://hub.docker.com/_/scratch を参照してください。

追加ファイルを使用したデプロイメント例

ここでは、以前の「Go Web ビデオ チュートリアル」の小さなリスト プロジェクトを例に挙げます。プロジェクトの Github リポジトリ アドレスは https://github.com/Q1mi/bubble です。

プロジェクトに静的ファイルまたは構成ファイルが含まれている場合は、それらを最終イメージ ファイルにコピーする必要があります。

私たちのバブル プロジェクトでは、静的ファイルと構成ファイルを使用します。具体的なディレクトリ構造は次のとおりです。

バブル
├── README.md
├── バブル
├── 会議
│ └── config.ini
├── コントローラー
│ └── コントローラー.go
├── ダオ
│ └── mysql.go
├── example.png
├── go.mod
├── go.sum
├── main.go
├── モデル
│ └── todo.go
├── ルーター
│ └── routers.go
├── 設定
│ └── 設定.go
├── 静的
│ ├── css
│ │ ├── app.8eeeaf31.css
│ │ └── chunk-vendors.57db8905.css
│ ├── フォント
│ │ ├── element-icons.535877f5.woff
│ │ └── element-icons.732389de.ttf
│ └── js
│ ├── app.007f9690.js
│ └── chunk-vendors.ddcb6f91.js
└── テンプレート
 ├── favicon.ico
 └──index.html

templates、static、conf フォルダーの内容を最終的なイメージ ファイルにコピーする必要があります。更新されたDockerfileは次のとおりです。

golang:alpine AS ビルダーから

# イメージに必要な環境変数 ENV GO111MODULE=on を設定します \
 CGO_ENABLED=0 \
 GOOS=Linux \
 GOARCH=amd64

# 作業ディレクトリに移動: /build
ワークディレクトリ /build

# プロジェクト内の go.mod および go.sum ファイルをコピーし、依存関係情報をダウンロードします。COPY go.mod 。
go.sum をコピーします。
RUN go mod ダウンロード

# コードをコンテナにコピーします COPY . .

# コードをバイナリ実行ファイルにコンパイルします
go build -o bubble を実行します。

###################
# 次に、小さなミラーを作成します#####################
ゼロから

コピー ./templates /templates
コピー ./static /static
コピー ./conf /conf

# ビルダーイメージから /dist/app を現在のディレクトリにコピーします COPY --from=builder /build/bubble /

# 実行するコマンド ENTRYPOINT ["/bubble", "conf/config.ini"]

簡単に言うと、COPY ステップがさらにいくつかあります。Dockerfile のコメントを見てください。

ヒント: ここでは、静的ファイルを上層にコピーし、バイナリ実行可能ファイルを下層にコピーする手順を配置し、より多くのキャッシュを使用するようにします。

他のコンテナへのリンク

このプロジェクトでは MySQL が使用されているため、次のコマンドで MySQL コンテナを起動できます。エイリアスは mysql8019、ルート ユーザーのパスワードは root1234、コンテナ内の /var/lib/mysql をローカルの /Users/q1mi/docker/mysql ディレクトリにマウントします。内部サービス ポートは 3306 で、外部ポート 13306 にマップされます。

docker run --name mysql8019 -p 13306:3306 -e MYSQL_ROOT_PASSWORD=root1234 -v /Users/q1mi/docker/mysql:/var/lib/mysql -d mysql:8.0.19

ここで、プログラムで構成されている MySQL ホスト アドレスをコンテナー エイリアスに変更して、エイリアス (ここでは mysql8019) を介して内部的に通信できるようにする必要があります。

[mysql]
ユーザー = ルート
パスワード = root1234
ホスト = mysql8019
ポート = 3306
db = バブル

変更後は必ず bubble_app イメージを再構築してください。

docker ビルド . -t bubble_app

ここで bubble_app コンテナを実行するときは、--link メソッドを使用して、上記の mysql8019 コンテナに関連付ける必要があります。具体的なコマンドは次のとおりです。

docker run --link=mysql8019:mysql8019 -p 8888:8888 bubble_app

Docker コンポーズモード

上記のように --link メソッドを使用して 2 つのコンテナを関連付けるだけでなく、Docker Compose を使用して複数のコンテナを定義して実行することもできます。

Compose は、マルチコンテナ Docker アプリケーションを定義および実行するためのツールです。 Compose では、YML ファイルを使用して、アプリケーションに必要なすべてのサービスを構成します。その後、1 つのコマンドで、YML ファイル構成からすべてのサービスを作成して起動できます。

Compose の使用は基本的に 3 つのステップで構成されます。

  1. Dockerfile を使用してアプリケーション環境を定義し、どこにでも複製できるようにします。
  2. アプリケーションを構成するサービスを docker-compose.yml で定義し、分離された環境で一緒に実行できるようにします。
  3. docker-compose up コマンドを実行して、アプリケーション全体を起動して実行します。

私たちのプロジェクトでは、それぞれ mysql と bubble_app を実行するための 2 つのコンテナが必要です。作成した docker-compose.yml ファイルの内容は次のとおりです。

#yaml 構成バージョン: "3.7"
サービス:
 mysql8019:
 イメージ: "mysql:8.0.19"
 ポート:
  - 「33061:3306」
 コマンド: "--default-authentication-plugin=mysql_native_password --init-file /data/application/init.sql"
 環境:
  MYSQL_ROOT_PASSWORD: "root1234"
  MYSQL_DATABASE: 「バブル」
  MYSQL_パスワード: "root1234"
 ボリューム:
  - ./init.sql:/data/application/init.sql
 バブルアプリ:
 建てる: 。
 コマンド: sh -c "./wait-for.sh mysql8019:3306 -- ./bubble ./conf/config.ini"
 依存:
  -mysql8019
 ポート:
  - 「8888:8888」

この Compose ファイルは、bubble_app と mysql8019 の 2 つのサービスを定義します。で:

バブルアプリ
現在のディレクトリにある Dockerfile ファイルを使用してイメージをビルドし、depends_on を通じて mysql8019 サービスへの依存関係を指定し、サービス ポート 8888 を宣言して、外部ポート 8888 をバインドします。

マイSQL8019
mysql8019 サービスは、内部ポート 3306 と外部ポート 33061 を使用して、Docker Hub のパブリック mysql:8.0.19 イメージを使用します。

ここで注意すべき点は、Web プログラムは起動時に MySQL 接続を初期化するため、bubble_app コンテナは起動を試みる前に、mysql8019 コンテナが正常に起動するのを待つ必要があることです。ここで変更する箇所は 2 か所あります。1 つ目は、Dockerfile の最後の文をコメント アウトすることです。

# Dockerファイル
...
# 実行するコマンド (Web プログラムを開始する前に MySQL が起動するまで待つ必要があるため、この文をコメント化します)
# エントリポイント ["/bubble", "conf/config.ini"]

2 番目は、bubble_app の下に次のコマンドを追加し、事前に記述された wait-for.sh スクリプトを使用して、mysql8019:3306 が正常であることを検出してから、後続のコマンドを実行して Web アプリケーションを起動することです。

コマンド: sh -c "./wait-for.sh mysql8019:3306 -- ./bubble ./conf/config.ini"

もちろん、bubble_app イメージで sh コマンドを実行するため、スクラッチ イメージを使用してビルドすることはできません。代わりに、debian:stretch-slim を使用します。同時に、wait-for.sh スクリプトで使用される netcat もインストールする必要があります。最後に、wait-for.sh スクリプト ファイルを最終イメージにコピーし、実行権限を付与することを忘れないでください。更新された Dockerfile の内容は次のとおりです。

golang:alpine AS ビルダーから

# イメージに必要な環境変数 ENV GO111MODULE=on を設定します \
 CGO_ENABLED=0 \
 GOOS=Linux \
 GOARCH=amd64

# 作業ディレクトリに移動: /build
ワークディレクトリ /build

# プロジェクト内の go.mod および go.sum ファイルをコピーし、依存関係情報をダウンロードします。COPY go.mod 。
go.sum をコピーします。
RUN go mod ダウンロード

# コードをコンテナにコピーします COPY . .

# コードをバイナリ実行ファイルにコンパイルします
go build -o bubble を実行します。

###################
# 次に、小さなミラーを作成します#####################
debian:stretch-slim より

コピー ./wait-for.sh /
コピー ./templates /templates
コピー ./static /static
コピー ./conf /conf


# ビルダーイメージから /dist/app を現在のディレクトリにコピーします COPY --from=builder /build/bubble /

実行set -eux; \
 apt-getアップデート; \
 apt-getインストール-y \
 --no-install-recommends \
 ネットキャット; \
  chmod 755 wait-for.sh

# 実行するコマンド # ENTRYPOINT ["/bubble", "conf/config.ini"]

すべての条件が準備できたら、次のコマンドを実行して実行できます。

docker-compose を起動する

完全なコード例については、私の github リポジトリ (https://github.com/Q1mi/deploy_bubble_using_docker) をご覧ください。

要約する

Docker コンテナを使用すると、依存環境の構成における操作が大幅に簡素化されますが、技術的なリソースに対する要求も高まります。 Docker に精通しているかどうかに関係なく、技術開発の車輪は前進し続けています。

参考リンク:

https://levelup.gitconnected.com/golang アプリケーション用の docker コンテナを作成するための完全なガイド-80f3fb59a15e

Docker を使用して Go Web アプリケーションをデプロイする方法についての記事はこれで終わりです。Go Web の Docker デプロイの詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Dockerを使用してDjango+MySQL8開発環境をデプロイする方法の詳細な説明
  • Centos8 で Docker を使用して Django プロジェクトをデプロイする詳細なチュートリアル
  • Docker イメージに基づいて Go プロジェクトをデプロイする方法と手順
  • GoのDockerデプロイメント用の基本イメージ2つの実装
  • docker を使用して influxdb と mongo をデプロイするための一般的なコマンド
  • Docker-compose を使用して Django アプリケーションをオフラインでデプロイする方法
  • Docker を使用して Django プロジェクトをデプロイする方法の例
  • Docker で Django アプリケーションをデプロイする例
  • docker を使用して Golang オンライン デプロイメント環境を構築する詳細な手順

<<:  HTML テーブル マークアップ チュートリアル (10): セル パディング属性 CELLPADDING

>>:  ElementUIはドロップダウンオプションと複数選択ボックスのサンプルコードを実装します

推薦する

MYSQL での Truncate の使用法の詳細な説明

この記事のガイド: テーブル内のデータを削除するには、削除と切り捨ての 2 つの方法があります。TR...

デザイナーと開発者に役立つ 9 つの超実用的な CSS のヒント

Web デザイナーの頭の中には、仕事に関連する多くの知識が詰まっている必要があります。 CSS は、...

ins タグと del タグの属性と使用法

insとdel は、HTML 4.0 で導入され、文書の作成時に作成者が共同作業できるようにし、また...

数百万のデータに対して MySQL クエリを最適化する 4 つの方法

目次1. 時間が経つにつれて限界が遅くなる理由2. 百万データシミュレーション1. 従業員テーブルと...

MySQLデータの挿入、更新、削除の詳細

目次1. 挿入2. 更新3. 削除1. 挿入 顧客に挿入( 顧客.顧客住所、 顧客.cust_cit...

MySQL パフォーマンス最適化のための魔法のツール、Explain の基本的な使用分析

導入MySQL には、SELECT ステートメントを分析し、開発者が最適化できるように SELECT...

MySQL における Decimal 型と Float Double 型の違い (詳細説明)

MySQL には、10 進数などの標準データ型だけでなく、float や double などの非標...

MySQL で重複レコードを見つけて削除する方法

みなさんこんにちは。私は技術の話ばかりして髪を切らない先生のトニーです。何らかの歴史的な理由や誤操作...

Nginx の break と last の違いの詳細な分析

まずは違いについて話しましょう最後に、書き換えられたルールは、次の場所と一致させるために書き換えられ...

HTML チュートリアル: 画像のサイズ、配置、間隔、境界線の属性を変更する方法

画像タグ: <img> ページに画像を挿入するには、「src」属性を持つ「img」タグを...

Docker で Jenkins-2.249.3-1.1 をインストールする詳細な手順

目次1. Dockerをインストールする2. Jenkinsイメージファイルを取得する3. マウント...

Dockerコンテナが停止できない問題の解決方法

解決策は次のとおりです。 1. コンテナを強制削除する docker rm -f ジェンキンス2. ...

シンプルなjQuery + CSSを使用してカスタムタグタイトルツールチップを作成します

導入シンプルな jQuery + CSS を使用して、ブラウザのデフォルトの動作を置き換えるカスタム...

Ubuntu 18.04 で SSH サービスをインストールして設定する方法

sshツールをインストールする1. ターミナルを開き、次のコマンドを入力します。 apt-getアッ...