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

著者はhttps://www.brightfunds.org/funds/foss-nonprofits [無料およびオープンソース基金]を選択して、https://do.co/w4do-cta [Donationsのために書く]の一部として寄付を受け取りましたプログラム。

前書き

Dockerは、今日使用されている最も一般的なコンテナ化ソフトウェアです。 開発者は、環境とともにアプリを簡単にパッケージ化できるため、実行のたびに同じ望ましい環境を提供しながら、反復サイクルを短縮し、リソース効率を向上させることができます。 Docker Composeは、最新のアプリ要件を容易にするコンテナーオーケストレーションツールです。 複数の相互接続されたコンテナを同時に実行できます。 コンテナを手動で実行する代わりに、オーケストレーションツールを使用すると、開発者はコンテナを同時に制御、スケーリング、および拡張できます。

NginxをフロントエンドWebサーバーとして使用する利点は、そのパフォーマンス、構成可能性、およびTLS終了です。これにより、アプリはこれらのタスクを完了できなくなります。 https://github.com/jwilder/nginx-proxy [+ nginx-proxy +]は、Dockerコンテナ用の自動化システムであり、リバースプロキシとして機能するようにNginxを構成するプロセスを大幅に簡素化します。 そのhttps://www.digitalocean.com/community/tutorials/an-introduction-to-let-s-encrypt[Let’s Encrypt] https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion [アドオン]は、プロキシされたコンテナの証明書の生成と更新を自動化するために、 `+ nginx-proxy +`に付随できます。

このチュートリアルでは、https://github.com/gorilla/mux [gorilla / mux]をリクエストルーターとして、NginxをWebサーバーとして、すべてのDockerコンテナー内にあるDocker Composeによって編成されたサンプルGo Webアプリケーションをデプロイします。 リバースプロキシとしてLet’s Encryptアドオンで `+ nginx-proxy +`を使用します。 このチュートリアルの最後で、Dockerを使用し、Let’s Encrypt証明書で保護された、複数のルートでドメインにアクセス可能なGoウェブアプリをデプロイします。

前提条件

  • ルート権限を持つUbuntu 18.04サーバー、およびセカンダリの非ルートアカウント。 これは、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04 [この初期サーバー設定ガイド]に従って設定できます。 このチュートリアルでは、非ルートユーザーは「++」です。

  • Ubuntu 18.04にDockerをインストールする方法の最初の2つの手順に従ってインストールされたDocker ]。

  • https://www.digitalocean.com/community/tutorials/how-to-install-docker-compose-on-ubuntu-18-04の最初の手順に従ってインストールされたDocker Compose [Ubuntu 18.04にDocker Composeをインストールする方法] 。 最初のステップを実行するだけです。

  • 完全に登録されたドメイン名。 このチュートリアルでは、全体で「++」を使用します。 Freenomで無料で入手するか、選択したドメインレジストラーを使用できます。

  • サーバーのパブリックIPアドレスを指す「++」を含むDNS「A」レコード。 追加方法の詳細については、https://www.digitalocean.com/docs/networking/dns/quickstart/ [この概要]からDigitalOcean DNSを参照してください。

  • Dockerとそのアーキテクチャの理解。 Dockerの概要については、https://www.digitalocean.com/community/tutorials/the-docker-ecosystem-an-introduction-to-common-components [The Docker Ecosystem:An Introduction to Common Components]を参照してください。

手順1-サンプルGo Webアプリの作成

この手順では、ワークスペースをセットアップし、簡単なGo Webアプリを作成します。これは後でコンテナー化されます。 Goアプリは、柔軟性と速度から選択された強力なhttps://github.com/gorilla/mux[gorilla/mux]リクエストルーターを使用します。

`+ sammy +`としてログインして開始します。

ssh @

このチュートリアルでは、すべてのデータを `+〜/ go-docker`に保存します。 これを行うには、次のコマンドを実行します。

mkdir ~/go-docker

それに移動します:

cd ~/go-docker

Go Webアプリの例は、 `+ main.go +`という名前のファイルに保存します。 テキストエディターを使用して作成します。

nano main.go

次の行を追加します。

main.go

package main

import (
   "fmt"
   "net/http"

   "github.com/gorilla/mux"
)

func main() {
   r := mux.NewRouter()

   r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
       fmt.Fprintf(w, "<h1>This is the homepage. Try /hello and /hello/Sammy\n</h1>")
   })

   r.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
       fmt.Fprintf(w, "<h1>Hello from Docker!\n</h1>")
   })

   r.HandleFunc("/hello/{name}", func(w http.ResponseWriter, r *http.Request) {
       vars := mux.Vars(r)
       title := vars["name"]

       fmt.Fprintf(w, "<h1>Hello, %s!\n</h1>", title)
   })

   http.ListenAndServe(":80", r)
}

まず、HTTPサーバーの機能とルーティングを提供する `+ net / http `および ` gorilla / mux +`パッケージをインポートします。

+ gorilla / mux +`パッケージは、より簡単で強力なリクエストルーターとディスパッチャーを実装すると同時に、標準ルーターとのインターフェース互換性を維持します。 ここでは、新しい「+ mux +」ルーターをインスタンス化し、変数「+ r +」に保存します。 次に、3つのルート、「+ / +」、「+ / hello +」、および「+ / hello / {name} +」を定義します。 最初の( `+ / +)はホームページとして機能し、ページのメッセージを含めます。 2番目( + / hello +)は、訪問者に挨拶を返します。 3番目のルート( + / hello / {name} +)では、名前をパラメーターとして使用し、名前が挿入されたグリーティングメッセージを表示するように指定します。

ファイルの最後で、 `+ http.ListenAndServe `でHTTPサーバーを起動し、設定したルーターを使用してポート ` 80 +`でリッスンするように指示します。

ファイルを保存して閉じます。

Goアプリを実行する前に、まずDockerコンテナー内で実行するためにコンパイルしてパックする必要があります。 Goはhttps://www.digitalocean.com/community/tutorials/how-to-write-your-first-program-in-go#step-2-%E2%80%94-running-a-go-ですプログラム[コンパイル言語]。プログラムを実行する前に、コンパイラはプログラミングコードを実行可能なマシンコードに変換します。

ワークスペースを設定し、Go Webアプリの例を作成しました。 次に、自動化されたLet’s Encrypt証明書プロビジョニングを使用して、 `+ nginx-proxy +`をデプロイします。

ステップ2-Let’s Encryptを使用したnginx-proxyのデプロイ

HTTPSでアプリを保護することが重要です。 これを達成するには、Let’s Encrypt add-onとともに、Docker Composeを介して `+ nginx-proxy `をデプロイします。 これにより、 ` nginx-proxy +`を使用してプロキシされたDockerコンテナが保護され、TLS証明書の作成と更新を自動的に処理することでHTTPSを介したアプリの保護が行われます。

「+ nginx-proxy 」のDocker Compose設定を「+」という名前のファイルに保存します。 次を実行して作成します。

nano

ファイルに次の行を追加します。

nginx-proxy-compose.yaml

version: '2'

services:
 nginx-proxy:
   restart: always
   image: jwilder/nginx-proxy
   ports:
     - "80:80"
     - "443:443"
   volumes:
     - "/etc/nginx/vhost.d"
     - "/usr/share/nginx/html"
     - "/var/run/docker.sock:/tmp/docker.sock:ro"
     - "/etc/nginx/certs"

 letsencrypt-nginx-proxy-companion:
   restart: always
   image: jrcs/letsencrypt-nginx-proxy-companion
   volumes:
     - "/var/run/docker.sock:/var/run/docker.sock:ro"
   volumes_from:
     - "nginx-proxy"

ここでは、2つのコンテナを定義しています。1つは「+ nginx-proxy 」用で、もう1つはLet's Encryptアドオン(「 letsencrypt-nginx-proxy-companion 」)用です。 プロキシの場合、イメージ「 jwilder / nginx-proxy +」を指定し、HTTPポートとHTTPSポートを公開およびマッピングし、最後にNginx関連データを保持するためにコンテナーにアクセスできるボリュームを定義します。

2番目のブロックでは、Let’s Encryptアドオン構成の画像に名前を付けます。 次に、ボリュームを定義してからDockerのソケットへのアクセスを設定し、次にプロキシコンテナから既存のボリュームを継承します。 どちらのコンテナにも `+ restart `プロパティが ` always +`に設定されており、Dockerに常にそれらを維持するように指示します(クラッシュまたはシステムの再起動の場合)。

ファイルを保存して閉じます。

次を実行して、 `+ nginx-proxy +`をデプロイします。

docker-compose -f  up -d

Docker Composeは、 `+ -f `フラグを介してカスタムの名前付きファイルを受け入れます。 ` up `コマンドはコンテナーを実行し、 ` -d +`フラグ(分離モード)は、コンテナーをバックグラウンドで実行するように指示します。

最終的な出力は次のようになります。

OutputCreating network "go-docker_default" with the default driver
Pulling nginx-proxy (jwilder/nginx-proxy:)...
latest: Pulling from jwilder/nginx-proxy
a5a6f2f73cd8: Pull complete
2343eb083a4e: Pull complete
...
Digest: sha256:619f390f49c62ece1f21dfa162fa5748e6ada15742e034fb86127e6f443b40bd
Status: Downloaded newer image for jwilder/nginx-proxy:latest
Pulling letsencrypt-nginx-proxy-companion (jrcs/letsencrypt-nginx-proxy-companion:)...
latest: Pulling from jrcs/letsencrypt-nginx-proxy-companion
...
Creating go-docker_nginx-proxy_1 ... done
Creating go-docker_letsencrypt-nginx-proxy-companion_1 ... done

「+ nginx-proxy +」とDocker Composeを使用してLet’s Encryptコンパニオンをデプロイしました。 次に、Go Webアプリ用のDockerfileを作成します。

ステップ3-Go WebアプリのDockerizing

このセクションでは、DockerがGo Webアプリの不変のイメージを作成する方法に関する手順を含むDockerfileを作成します。 Dockerは、Dockerfileにある指示を使用して、コンテナのスナップショットに類似した不変のアプリイメージを構築します。 画像の不変性は、特定の画像に基づいてコンテナが実行されるたびに同じ環境を保証します。

テキストエディターで `+ Dockerfile`を作成します。

nano Dockerfile

次の行を追加します。

Dockerfile

FROM golang:alpine AS build
RUN apk --no-cache add gcc g++ make git
WORKDIR /go/src/app
COPY . .
RUN go get ./...
RUN GOOS=linux go build -ldflags="-s -w" -o ./bin/web-app ./main.go

FROM alpine:3.9
RUN apk --no-cache add ca-certificates
WORKDIR /usr/bin
COPY --from=build /go/src/app/bin /go/bin
EXPOSE 80
ENTRYPOINT /go/bin/web-app --port 80

このDockerfileには2つの段階があります。 最初の段階では、Alpine LinuxにプリインストールされたGoが含まれる `+ golang:alpine +`ベースを使用します。

次に、Goアプリに必要なコンパイルツールとして、「+ gcc」、「+ g +」、「 make」、および「+ git 」をインストールします。 作業ディレクトリを ` / go / src / app `に設定します。これはデフォルトのhttps://www.digitalocean.com/community/tutorials/understanding-the-gopath[GOPATH]の下にあります。 また、現在のディレクトリのコンテンツをコンテナにコピーします。 最初の段階は、コードから使用されたパッケージを再帰的に取得し、シンボルとデバッグ情報なしでリリースするために ` main.go `ファイルをコンパイルすることで終了します( ` -ldflags ="-s -w "+`を渡します)。 Goプログラムをコンパイルすると、デバッグに使用されるバイナリの別の部分が保持されますが、この追加情報はメモリを使用するため、実稼働環境にデプロイする際に保存する必要はありません。

2番目のステージは、 + alpine:3.9 +(Alpine Linux 3.9)に基づいています。 信頼できるCA証明書をインストールし、コンパイルされたアプリバイナリを最初の段階から現在のイメージにコピーし、ポート「80」を公開し、アプリバイナリをイメージエントリポイントとして設定します。

ファイルを保存して閉じます。

Goアプリ用のDockerfileを作成しました。Dockerfileは、パッケージを取得し、リリース用にコンパイルし、コンテナー作成時に実行します。 次のステップでは、Docker Compose `+ yaml +`ファイルを作成し、Dockerで実行してアプリをテストします。

ステップ4-Docker Composeファイルの作成と実行

次に、Docker Compose構成ファイルを作成し、前の手順で作成したDockerイメージを実行するために必要な構成を記述します。 次に、それを実行し、正しく機能するかどうかを確認します。 一般に、Docker Compose構成ファイルは、アプリが必要とするコンテナー、その設定、ネットワーク、およびボリュームを指定します。 これらの要素を同時に開始および停止できるように指定することもできます。

Go WebアプリのDocker Compose設定を「++」という名前のファイルに保存します。 次を実行して作成します。

nano

このファイルに次の行を追加します。

go-app-compose.yaml

version: '2'
services:
 go-web-app:
   restart: always
   build:
     dockerfile: Dockerfile
     context: .
   environment:
     - VIRTUAL_HOST=
     - LETSENCRYPT_HOST=

必ず `++`をドメイン名に置き換えてください。 ファイルを保存して閉じます。

このDocker Compose構成には、Go Webアプリになるコンテナー( + to-web-app)が1つ含まれています。 前の手順で作成したDockerfileを使用してアプリをビルドし、ビルドのコンテキストとしてソースコードを含む現在のディレクトリを取得します。 さらに、2つの環境変数を設定します: + VIRTUAL_HOST +`と `+ LETSENCRYPT_HOST ++ nginx-proxy`は、リクエストを受け付けるドメインを知るために + VIRTUAL HOST`を使用します。 `+ LETSENCRYPT_HOST `は、TLS証明書を生成するためのドメイン名を指定します。ワイルドカードドメインを指定しない限り、 ` VIRTUAL_HOST +`と同じでなければなりません。

次に、次のコマンドを使用して、Docker Composeを介してバックグラウンドでGo Webアプリを実行します。

docker-compose -f go-app-compose.yaml up -d

最終的な出力は次のようになります。

OutputCreating network "go-docker_default" with the default driver
Building go-web-app
Step 1/12 : FROM golang:alpine AS build
---> b97a72b8e97d
...
Successfully tagged go-docker_go-web-app:latest
WARNING: Image for service go-web-app was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating go-docker_go-web-app_1 ... done

コマンドの実行後に表示される出力を確認すると、Dockerは、Dockerfileの構成に従ってアプリイメージを構築するすべてのステップを記録しました。

これで、 `+ https:/// `に移動してホームページを表示できます。 ウェブアプリの自宅の住所には、最初のステップで定義した「 / +」ルートの結果としてページが表示されます。

image:https://assets.digitalocean.com/articles/godockernginx/step4a.png [これはホームページです。 / helloと/ hello / Sammyを試してください]

ここで、 `+ https:/// hello `に移動します。 手順1の ` / hello +`ルートに対してコードで定義したメッセージが表示されます。

画像:https://assets.digitalocean.com/articles/godockernginx/step4b.png [Dockerからこんにちは!]

最後に、Webアプリのアドレスに名前を追加して、「+ https:/// hello / Sammy +」のような他のルートをテストしてください。

画像:https://assets.digitalocean.com/articles/godockernginx/step4c.png [こんにちは、サミー!]

コンテナ内でGoアプリを実行するためのDocker Composeファイルと記述された構成を作成しました。 最後に、ドメインに移動して、 `+ gorilla / mux +`ルーターのセットアップがDockerized Go Webアプリへのリクエストを正しく処理していることを確認しました。

結論

これで、Ubuntu 18.04にDockerおよびNginxを使用してGo Webアプリを正常にデプロイできました。 Dockerを使用すると、アプリケーションが実行されるたびに同じ環境が保証されるため、アプリケーションのメンテナンスが面倒になりません。 gorilla/muxパッケージには優れたドキュメントがあり、ルートの命名や静的ファイルの提供など、より洗練された機能を提供します。 カスタムタイムアウトの定義など、Go HTTPサーバーモジュールの詳細な制御については、https://golang.org/pkg/net/http/ [official docs]にアクセスしてください。

Related