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はドロップダウンオプションと複数選択ボックスのサンプルコードを実装します

推薦する

Nginx 逆生成 Mogilefs 分散ストレージ例の詳細な説明

1. 分散ストレージシステムの概要情報技術の継続的な発展により、利便性がもたらされる一方で、データ量...

React 構成 px 変換 rem メソッド

関連する依存関係をインストールするnpm i lib-flexible --save npm i p...

mysql5.6.8 ソースコードのインストールプロセス

カーネル: [root@opop ~]# cat /etc/centos-release CentO...

ルート変更を監視するJavaScriptの詳細な説明

目次歴史pushState() メソッドpushState() の使用シナリオreplaceStat...

MySQL 5.7 のインストールと設定のチュートリアル

この記事では、参考までにMySQLのインストールと設定のチュートリアルを紹介します。具体的な内容は次...

高さ:100% が機能しないのはなぜですか?

高さ:100% が機能しないのはなぜですか?この知識は不人気ではありませんが、使用する際には混乱する...

適応幅(パーセンテージ)に応じて Div の高さを調整する純粋な CSS

今日のレスポンシブ レイアウトの要件では、サイズを自動的に調整できる多くの要素で高さと幅の適応を実現...

CSS で「プラス記号」効果を実装するためのサンプルコード

以下に示すプラス記号の効果を実現するには: この効果を実現するには、div 要素だけが必要です。 b...

MySQL が暗黙のデフォルト値を処理する方法

何人かの学生は、マスターとスレーブの間の不一致の問題に遭遇したと述べました。一般的な状況としては、m...

Link と @import の違いを詳しく見る

ページで CSS を使用する主な方法は、スタイル属性値をインラインで追加する方法、ページ ヘッダーで...

MySQL CHARとVARCHARの保存と読み取りの違い

導入保存時と読み取り時に CHAR 型と VARCHAR 型の違いを本当にご存知ですか?まずいくつか...

Dockerは終了状態で起動します

docker run後、ステータスは常にExitedになります解決:パラメータを追加: -it do...

自己終了XHTMLタグを書くときに注意すべきこと

XHTML の img タグはいわゆる自己終了タグであり、XML では完全に合法です。 XHTMLの...

本番環境でのMySQLパラメータsql_safe_updatesの使用に関する詳細な説明

序文アプリケーションのバグや DBA の誤操作が発生した場合、テーブル全体が更新される可能性がありま...

React.cloneElement の使い方の詳しい説明

目次cloneElementの役割使用シナリオ新しい小道具を追加するプロップを変更するイベントカスタ...