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

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

介绍

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

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

在本教程中,您将部署一个 Go Web 应用程序的示例 gorilla/mux作为请求路由器和 Nginx 作为 Web 服务器,所有在 Docker 容器内,由 Docker Compose 组织。您将使用 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'软件包执行一个更简单更强大的请求路由器和调度器,同时保持与标准路由器的接口相容性. 在这里,你即用一个新的 " mux " 路由器并将其存储在可变 " r " 中。 然后,你定义了三条路线:/'、/hello'和/hello/{name}'。 第一页( " / " )作为主页,其中包含该页的信息。 第二个( " /hello " )向来访者问候。 对于第三条路由(/hello/{name}>),您指定它应该取出一个名称作为参数,并显示带有所插入名称的问候信息.

在文件的末尾,您将启动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: '2'
 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通过-f旗声接受一个自定义名为的文件. up命令运行容器,而-d旗帜,分离模式,指示它在背景中运行容器。

你的最终结果将是这样的:

 1[secondary_label Output]
 2Creating network "go-docker_default" with the default driver
 3Pulling nginx-proxy (jwilder/nginx-proxy:)...
 4latest: Pulling from jwilder/nginx-proxy
 5a5a6f2f73cd8: Pull complete
 62343eb083a4e: Pull complete
 7...
 8Digest: sha256:619f390f49c62ece1f21dfa162fa5748e6ada15742e034fb86127e6f443b40bd
 9Status: Downloaded newer image for jwilder/nginx-proxy:latest
10Pulling letsencrypt-nginx-proxy-companion (jrcs/letsencrypt-nginx-proxy-companion:)...
11latest: Pulling from jrcs/letsencrypt-nginx-proxy-companion
12...
13Creating go-docker_nginx-proxy_1 ... done
14Creating go-docker_letsencrypt-nginx-proxy-companion_1 ... done

您已经部署了「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.13
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: '2'
 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/12 : FROM golang:alpine AS build
5 ---> b97a72b8e97d
6...
7Successfully tagged go-docker_go-web-app:latest
8WARNING: 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`.
9Creating go-docker_go-web-app_1 ... done

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

您现在可以导航到 https://your_domain/ 查看您的主页. 在您的 Web 应用程序的主地址,您正在看到页面作为您在第一步中定义的 / 路线的结果。

This is the homepage. Try /hello and /hello/Sammy

现在导航到 https://your_domain/hello. 您将从步骤 1 看到您在代码中定义的 /hello 路线的消息。

Hello from Docker!

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

Hello, Sammy!

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

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

结论

你现在已经成功部署 Go web app with Docker and Nginx on Ubuntu 18.04 (英语). 和多克一起,维持应用程序变得不那么麻烦了,因为每次运行时,被执行的应用程序所处环境保证是相同的. gorilla/mux包有出色的文档,并提供更精密的特征,例如命名路线并服务静态文件. 对于Go HTTP 服务器模块的更多控制,例如定义自定义超时,访问official docs.

Published At
Categories with 技术
comments powered by Disqus