如何在 Ubuntu 22.04 上使用 Docker 和 Nginx 部署 Go 网络应用程序

_ 作者选择了 免费和开源基金作为 写给捐款计划的一部分接受捐款。

介绍

[Docker] (https://www.docker.com/)是一款常用的容器化软件,使开发者能够轻松地随其环境一起包装应用软件,允许更快的迭代周期和更好的资源效率,同时在每次运行时提供同样理想的环境. [Docker Confose] (https://docs.docker.com/compose/)是便利现代应用要求的容器管弦乐工具. 它允许您同时运行多个互联的容器. 管弦乐工具不是手工操作的容器,而是赋予开发者同时控制,缩放,并扩展容器的能力.

使用Nginx作为前端网络服务器的好处在于性能,可配置性,以及TLS终止,这让应用程序可以自由完成这些任务. nginx-proxy是多克容器的自动化系统,简化了将Nginx配置为倒置代用的程序. 它让我们加密[接 (https://github.com/nginx-proxy/acme-companion)可以伴随"nginx-proxy"自动生成并更新代用容器证书.

在本教程中,您将部署一个 Go Web 应用程序的示例 gorilla/mux作为请求路由器和 Nginx 作为 Web 服务器,所有这些都是由 Docker Compose 主办的 Docker 容器。您将使用 nginx-proxy 与 Let's Encrypt 插件作为反向代理程序。本教程结束时,您将部署一个 Go Web 应用程序,可在您的域名上使用多个路由,使用 Docker 并使用 Let's Encrypt 证书。

前提条件

步骤 1 — 创建一个示例Go Web App

在此步骤中,您将设置您的工作空间,并创建一个简单的GoWeb应用程序,您将随后集装。Go应用程序将使用强大的 gorilla/mux请求路由器,其灵活性和速度选择。

对于本教程,您将存储所有数据在~/go-docker下,运行以下命令来创建此文件夹:

1mkdir ~/go-docker

导航它:

1cd ~/go-docker

您将您的示例 Go Web 应用程序存储在名为 main.go 的文件中. 使用文本编辑器创建它:

1nano main.go

添加以下几行:

 1[label ~/go-docker/main.go]
 2package main
 3
 4import (
 5    "fmt"
 6    "net/http"
 7
 8    "github.com/gorilla/mux"
 9)
10
11func main() {
12    r := mux.NewRouter()
13
14    r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
15    	fmt.Fprintf(w, "<h1>This is the homepage. Try /hello and /hello/Sammy\n</h1>")
16    })
17
18    r.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
19    	fmt.Fprintf(w, "<h1>Hello from Docker!\n</h1>")
20    })
21
22    r.HandleFunc("/hello/{name}", func(w http.ResponseWriter, r *http.Request) {
23    	vars := mux.Vars(r)
24    	title := vars["name"]
25
26    	fmt.Fprintf(w, "<h1>Hello, %s!\n</h1>", title)
27    })
28
29    http.ListenAndServe(":80", r)
30}

你首先导入net/httpgorilla/mux套件,这些套件提供HTTP服务器功能和路由。gorilla/mux套件实现了更强大的请求路由器和发送器,同时保持与标准路由器的接口兼容性。

然后,您定义了三个路径: /, /hello,和 /hello/{name}. 第一条路径(/)作为主页,您添加了该页面的消息。 第二条路径(/hello)向访问者返回问候。

在文件的末尾,您将启动HTTP服务器以http.ListenAndServe,并指示它在端口80上聆听,使用您配置的路由器。

保存并关闭文件。

在运行 Go 应用之前,您需要在 Docker 容器内编译并包装以执行。 Go 是一个 编译语言,因此在一个程序可以运行之前,编译器将编程代码翻译成可执行的机器代码。

您已经设置了工作区并创建了一个示例 Go Web 应用程序,接下来,您将部署nginx-proxy与自动的 Let's Encrypt 证书提供。

步骤 2 — 使用 Let's Encrypt 部署 nginx 代理

要做到这一点,您将通过 Docker Compose 部署「nginx-proxy」,以及其 Let's Encrypt add-on

您将将nginx-proxy的Docker Compose配置存储在名为nginx-proxy-compose.yaml的文件中。

1nano nginx-proxy-compose.yaml

将以下行添加到文件中:

 1[label ~/go-docker/nginx-proxy-compose.yaml]
 2version: '3'
 3
 4services:
 5  nginx-proxy:
 6    restart: always
 7    image: jwilder/nginx-proxy
 8    ports:
 9      - "80:80"
10      - "443:443"
11    volumes:
12      - "/etc/nginx/vhost.d"
13      - "/usr/share/nginx/html"
14      - "/var/run/docker.sock:/tmp/docker.sock:ro"
15      - "/etc/nginx/certs"
16
17  letsencrypt-nginx-proxy-companion:
18    restart: always
19    image: jrcs/letsencrypt-nginx-proxy-companion
20    volumes:
21      - "/var/run/docker.sock:/var/run/docker.sock:ro"
22    volumes_from:
23      - "nginx-proxy"

在此文件中,您定义了两个容器:一个为).对于代理,您指定图像jwilder/nginx-proxy,曝光和地图 HTTP 和 HTTPS 端口,并定义将可访问容器的卷,以便持久的 Nginx 相关数据。

在第二个块中,您将为 Let's Encrypt 插件配置命名图像。然后,您将通过定义一个卷来配置访问 Docker 插件,然后从代理容器继承现有的卷。

保存并关闭文件。

通过运行nginx-proxy部署:

1docker compose -f nginx-proxy-compose.yaml up -d

Docker Compose通过)指示它在背景中运行容器。

你会收到这样的输出:

 1[secondary_label Output]
 2[+] Running 21/21
 3 ⠿ letsencrypt-nginx-proxy-companion Pulled 6.8s
 4   ⠿ df9b9388f04a Pull complete 3.1s
 5   ⠿ 6c6cfd4eaf5b Pull complete 3.9s
 6   ⠿ 870307501973 Pull complete 4.3s
 7   ⠿ e8ff3435d14f Pull complete 4.5s
 8   ⠿ 5b78ba945919 Pull complete 4.8s
 9   ⠿ 973b2ca26006 Pull complete 5.0s
10 ⠿ nginx-proxy Pulled 8.1s
11   ⠿ 42c077c10790 Pull complete 3.9s
12   ⠿ 62c70f376f6a Pull complete 5.5s
13   ⠿ 915cc9bd79c2 Pull complete 5.6s
14   ⠿ 75a963e94de0 Pull complete 5.7s
15   ⠿ 7b1fab684d70 Pull complete 5.7s
16   ⠿ db24d06d5af4 Pull complete 5.8s
17   ⠿ e917373dbecf Pull complete 5.9s
18   ⠿ 11e2be9775e9 Pull complete 5.9s
19   ⠿ 9996fa75bc02 Pull complete 6.1s
20   ⠿ d37674efdf77 Pull complete 6.3s
21   ⠿ a45d84576e75 Pull complete 6.3s
22   ⠿ a13c1f42faf7 Pull complete 6.4s
23   ⠿ 4f4fb700ef54 Pull complete 6.5s
24[+] Running 3/3
25 ⠿ Network go-docker_default Created 0.1s
26 ⠿ Container go-docker-nginx-proxy-1 Started 0.5s
27 ⠿ Container go-docker-letsencrypt-nginx-proxy-companion-1 Started 0.8s

您已经部署了「nginx-proxy」及其使用 Docker Compose 的 Let's Encrypt 伴侣,接下来,您将为您的 Go Web 应用程序创建一个「Dockerfile」。

步骤 3 – 对 Go Web App 进行 Dockerizing

在本节中,您将准备一个Dockerfile,其中包含有关 Docker 如何为您的 Go Web 应用程序创建不可变的图像的说明。

使用您的文本编辑器创建Dockerfile:

1nano Dockerfile

添加以下几行:

 1[label ~/go-docker/Dockerfile]
 2FROM golang:alpine AS build
 3RUN apk --no-cache add gcc g++ make git
 4WORKDIR /go/src/app
 5COPY . .
 6RUN go mod init webserver
 7RUN go mod tidy
 8RUN GOOS=linux go build -ldflags="-s -w" -o ./bin/web-app ./main.go
 9
10FROM alpine:3.17
11RUN apk --no-cache add ca-certificates
12WORKDIR /usr/bin
13COPY --from=build /go/src/app/bin /go/bin
14EXPOSE 80
15ENTRYPOINT /go/bin/web-app --port 80

此 Dockerfile 有兩個階段. 第一個階段使用了「golang:alpine」基礎,其中包含在 Alpine Linux 上預先安裝的 Go。

然后安装 " gcc " 、 " gQ " 、 " make " 和 " git " 作为必要的汇编工具。 去应用。 您将工作目录设置为) 。 您还将当前目录的内容复制到容器中 。 第一阶段最后从代码中递归取出所使用的包并编译出"main.go"文件,无符号发布并调试信息(通过"-ldflags="-s-w").

注意: 当您编译Go程序时,它保留了用于调试的二进制的单独部分;然而,这种额外的信息使用了内存,并且在部署到生产环境时不需要保存。

第二阶段基于)。它安装了可信的CA证书,将编译的应用程序二进制从第一阶段复制到当前图像,暴露了端口80,并将应用程序二进制设置为图像输入点。

保存并关闭文件。

您已经为您的 Go 应用程序创建了 Dockerfile,该应用程序将收集其包,编译用于发布,并在创建容器时运行它。

第4步:创建和运行Docker组件文件

现在,您将创建 Docker Compose 配置文件并写入您在上一步创建的 Docker 图像运行所需的配置,然后,您将运行它并检查它是否正常工作。

您将将 Go Web 应用程序的 Docker Compose 配置存储在名为 go-app-compose.yaml 的文件中。

1nano go-app-compose.yaml

将以下行添加到此文件中:

 1[label ~/go-docker/go-app-compose.yaml]
 2version: '3'
 3services:
 4  go-web-app:
 5    restart: always
 6    build:
 7      dockerfile: Dockerfile
 8      context: .
 9    environment:
10      - VIRTUAL_HOST=your_domain
11      - LETSENCRYPT_HOST=your_domain

两次用您的域名替换 your_domain. 保存并关闭文件。

这个 Docker 编译配置包含一个容器( ) , 它将是您的 去网络应用。 它使用您在上一个步骤中创建的 Dockerfile 构建应用程序,并以包含源代码的当前目录作为构建的背景. 此外,它规定了两个环境变量:VIRTUAL-HOST ' 和LETSENCRYPT-HOST ' 。 LETSENCRYPT-Host'指定生成 TLS 证书的域名,并且必须与VIRTUAL-Host'相同,除非您指定了通配符域.

现在,通过 Docker Compose 在背景中运行您的 Go Web 应用程序:

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

这样的一种输出将打印(此输出已被缩小以便可读性):

 1[secondary_label Output]
 2Creating network "go-docker_default" with the default driver
 3Building go-web-app
 4Step 1/13 : FROM golang:alpine AS build
 5 ---> b97a72b8e97d
 6...
 7Successfully built 71e4b1ef2e25
 8Successfully tagged go-docker_go-web-app:latest
 9...
10[+] Running 1/1
11 ⠿ Container go-docker-go-web-app-1 Started

如果您在运行命令后审查所示的输出,Docker 会根据您的Dockerfile中的配置记录构建应用程序图像的每个步骤。

您现在可以导航到 https://your_domain/ 访问您的主页. 在您的 Web 应用程序的首页地址,您可以访问该页面,因为您在第一步中定义的 / 路线。

Screencapture of the domain page, which reads "This is the homepage. Try /hello and /hello/Sammy"

现在导航到 https://your_domain/hello. 您在您的代码中定义的 /hello 路由从步骤 1 将加载。

Screencapture of the <code>/hello</code> route, which reads "Hello from Docker!"

最后,添加一个名称到您的Web应用程序的地址来测试其他路线,例如: https://your_domain/hello/Sammy

Screencapture of the name route, which you have input as "Sammy" and reads "Hello, Sammy!"

注意: 如果您收到有关无效的 TLS 证书的错误,请等待几分钟,让 Let's Encrypt 插件提供证书。

您已创建了 Docker Compose 文件和编写的配置,以便在容器中运行您的 Go 应用程序. 最后,您导航到您的域,以检查gorilla/mux路由器设置是否正确地向您的 Dockerized Go Web 应用程序提供请求。

结论

你现在已经成功部署 在Ubuntu22.04上与多克和Nginx一起去网络应用. 与多克一起,维护应用程序并不那么花时间,因为应用程序被执行的环境保证每次运行时都会是相同的. gorilla/mux包有出色的文档,并提供更精密的特征,例如命名路线并服务静态文件. 对于Go HTTP 服务器模块的更多控制,例如定义自定义超时,访问official docs.

Published At
Categories with 技术
comments powered by Disqus