Как развернуть веб-приложение Go с помощью Docker и Nginx в Ubuntu 18.04

Автор выбрал Free и Open Source Fund, чтобы получить пожертвование как часть Write for DOnations program.

Вступление

Docker - наиболее распространенное на сегодняшний день программное обеспечение для контейнеризации. Это позволяет разработчикам легко упаковать приложения вместе со своими средами, что позволяет ускорить циклы итераций и повысить эффективность использования ресурсов, обеспечивая при этом одну и ту же желаемую среду при каждом запуске. Docker Compose - это инструмент для управления контейнером, который удовлетворяет современным требованиям приложений. Это позволяет запускать несколько взаимосвязанных контейнеров одновременно. Вместо ручного запуска контейнеров инструменты оркестровки дают разработчикам возможность одновременно контролировать, масштабировать и расширять контейнер.

Преимуществами использования Nginx в качестве интерфейсного веб-сервера являются его производительность, конфигурируемость и завершение TLS, что освобождает приложение от выполнения этих задач. Https://github.com/jwilder/nginx-proxy [+ nginx-proxy +] - это автоматизированная система для контейнеров Docker, которая значительно упрощает процесс настройки Nginx в качестве обратного прокси-сервера. Его Let’s Encrypt https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion [ дополнение] может сопровождать + nginx-proxy + для автоматизации создания и обновления сертификатов для прокси-контейнеров.

В этом учебном пособии вы развернете пример веб-приложения Go с gorilla/mux в качестве маршрутизатора запросов и Nginx в качестве веб-сервера, все внутри контейнеров Docker, организованных Docker Compose. В качестве обратного прокси вы будете использовать + nginx-proxy + с надстройкой Let’s Encrypt. В конце этого руководства вы развернете веб-приложение Go, доступное в вашем домене по нескольким маршрутам с использованием Docker и защищенное с помощью сертификатов Let Encrypt.

Предпосылки

  • Сервер Ubuntu 18.04 с привилегиями root и вторичной учетной записью без полномочий root. Вы можете настроить это, следуя https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04, приведенным в этом руководстве по первоначальной настройке сервера]. Для этого урока пользователь без полномочий root ++.

  • Docker установлен, выполнив первые два шага Как установить Docker в Ubuntu 18.04 .

  • Docker Compose устанавливается, следуя первому шагу Как установить Docker Compose в Ubuntu 18.04 , Вам нужно только сделать первый шаг.

  • Полностью зарегистрированное доменное имя. Этот урок будет использовать ++ повсюду. Вы можете получить его бесплатно на Freenom или использовать регистратор домена по вашему выбору.

  • DNS-запись «A» с ++, указывающая на публичный IP-адрес вашего сервера. Вы можете выполнить this вводная информация в DNS DigitalOcean для получения подробной информации о том, как их добавить.

  • Понимание Docker и его архитектуры. Для ознакомления с Docker см. Https://www.digitalocean.com/community/tutorials/the-docker-ecosystem-an-introduction-to-common-components[The экосистема Docker: Введение в общие компоненты].

Шаг 1. Создание примера Go Web App

На этом шаге вы настроите свою рабочую область и создадите простое веб-приложение Go, которое позже вы будете контейнеризировать. Приложение Go будет использовать мощный маршрутизатор запросов gorilla/mux, выбранный за его гибкость и скорость.

Начните с входа в систему как + sammy +:

ssh @

Для этого урока вы будете хранить все данные в + ~ / go-docker. Выполните следующую команду, чтобы сделать это:

mkdir ~/go-docker

Перейдите к нему:

cd ~/go-docker

Вы будете хранить пример веб-приложения Go в файле с именем + 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)
}

Сначала вы импортируете пакеты + net / http + и + gorilla / mux +, которые обеспечивают функциональность HTTP-сервера и маршрутизацию.

Пакет + gorilla / mux + реализует более простой и мощный маршрутизатор и диспетчер запросов, одновременно поддерживая совместимость интерфейса со стандартным маршрутизатором. Здесь вы создаете новый маршрутизатор + mux + и сохраняете его в переменной + r +. Затем вы определяете три маршрута: + / +, + / hello + и + / hello / {name} +. Первый (+ / +) служит домашней страницей, и вы включаете сообщение для этой страницы. Второй (+ / hello +) возвращает приветствие посетителю. Для третьего маршрута (+ / hello / {name} +) вы указываете, что он должен принимать имя в качестве параметра и показывать приветственное сообщение с вставленным именем.

В конце вашего файла вы запускаете HTTP-сервер с + http.ListenAndServe + и инструктируете его прослушивать порт + 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- program [скомпилированный язык], поэтому перед запуском программы компилятор преобразует программный код в исполняемый машинный код.

Вы настроили свое рабочее пространство и создали пример веб-приложения Go. Затем вы развернете + nginx-proxy + с автоматическим предоставлением сертификата Let Encrypt.

Шаг 2 - Развертывание nginx-прокси с Let’s Encrypt

Важно, чтобы вы защищали свое приложение с помощью HTTPS. Для этого вам нужно развернуть + nginx-proxy + через Docker Compose, вместе с его Let Encrypt add-on. Это обеспечивает защиту прокси-контейнеров Docker с использованием + nginx-proxy + и обеспечивает защиту вашего приложения через HTTPS путем автоматической обработки создания и обновления сертификатов TLS.

Вы будете хранить конфигурацию Docker Compose для + nginx-proxy + в файле с именем ++. Создайте его, запустив:

nano

Добавьте следующие строки в файл:

Nginx прокси-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"

Здесь вы определяете два контейнера: один для + nginx-proxy + и один для его дополнения Let Encrypt (+ letsencrypt-nginx-proxy-companion +). Для прокси вы указываете изображение + jwilder / nginx-proxy +, открываете и отображаете порты HTTP и HTTPS и, наконец, определяете тома, которые будут доступны контейнеру для сохранения данных, связанных с Nginx.

Во втором блоке вы называете изображение для конфигурации дополнения Let’s Encrypt. Затем вы настраиваете доступ к сокету Docker, определяя том, а затем существующие тома из прокси-контейнера для наследования. Оба контейнера имеют свойство + restart +, установленное в + всегда +, что указывает 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 + и его компаньон Let’s Encrypt с помощью Docker Compose. Затем вы создадите Dockerfile для своего веб-приложения Go.

Шаг 3. Докеризация веб-приложения Go

В этом разделе вы создадите Dockerfile, содержащий инструкции о том, как Docker создаст неизменный образ для вашего веб-приложения Go. 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 состоит из двух этапов. На первом этапе используется база + golang: alpine +, которая содержит предустановленную версию Go на Alpine Linux.

Затем вы устанавливаете + gcc,` + g + `,` + make` и ` git ` как необходимые инструменты компиляции для вашего приложения Go. Вы устанавливаете рабочий каталог ` / go / src / app `, который находится по умолчанию по адресу https://www.digitalocean.com/community/tutorials/understanding-the-gopath[GOPATH]. Вы также копируете содержимое текущего каталога в контейнер. Первый этап завершается рекурсивной выборкой пакетов, использованных из кода, и компиляцией файла ` main.go ` для выпуска без символа и информации отладки (путем передачи ` -ldflags =" - s -w "+`). Когда вы компилируете программу Go, она сохраняет отдельную часть двоичного файла, которая будет использоваться для отладки, однако эта дополнительная информация использует память и ее не нужно сохранять при развертывании в производственной среде.

Второй этап основан на + alpine: 3.9 + (Alpine Linux 3.9). Он устанавливает доверенные сертификаты CA, копирует скомпилированные двоичные файлы приложения с первого этапа в текущий образ, предоставляет порт + 80 + и устанавливает двоичный файл приложения в качестве точки входа в образ.

Сохраните и закройте файл.

Вы создали Dockerfile для своего приложения Go, которое будет извлекать его пакеты, компилировать его для выпуска и запускать при создании контейнера. На следующем шаге вы создадите файл Docker Compose + yaml + и протестируете приложение, запустив его в Docker.

Шаг 4 - Создание и запуск файла Docker Compose

Теперь вы создадите файл конфигурации Docker Compose и напишите необходимую конфигурацию для запуска образа Docker, созданного на предыдущем шаге. Затем вы запустите его и убедитесь, что он работает правильно. В общем, файл конфигурации Docker Compose определяет контейнеры, их настройки, сети и тома, которые требуются приложению. Вы также можете указать, что эти элементы могут запускаться и останавливаться как один одновременно.

Вы будете хранить конфигурацию Docker Compose для веб-приложения Go в файле с именем ++. Создайте его, запустив:

nano

Добавьте следующие строки в этот файл:

гоу-приложение-compose.yaml

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

Не забудьте заменить ++ оба раза на ваше доменное имя. Сохраните и закройте файл.

Эта конфигурация Docker Compose содержит один контейнер (+ to-web-app), который будет вашим веб-приложением Go. Он создает приложение, используя Dockerfile, созданный на предыдущем шаге, и принимает текущий каталог, содержащий исходный код, в качестве контекста для сборки. Кроме того, он устанавливает две переменные окружения: + VIRTUAL_HOST + и + LETSENCRYPT_HOST +. + nginx-proxy + использует + VIRTUAL_HOST +, чтобы узнать, с какого домена принимать запросы. + LETSENCRYPT_HOST + указывает имя домена для генерации сертификатов TLS и должно совпадать с + VIRTUAL_HOST +, если не указан домен с подстановочными знаками.

Теперь вы запустите веб-приложение Go в фоновом режиме с помощью Docker Compose с помощью следующей команды:

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: /// +, чтобы увидеть свою домашнюю страницу. По домашнему адресу вашего веб-приложения вы видите страницу в результате маршрута + / +, который вы определили на первом шаге.

изображение: https: //assets.digitalocean.com/articles/godockernginx/step4a.png [Это домашняя страница. Попробуй / привет и / привет / Сэмми]

Теперь перейдите к + https: /// hello +. Вы увидите сообщение, которое вы определили в своем коде для маршрута + / hello + из шага 1.

изображение: https: //assets.digitalocean.com/articles/godockernginx/step4b.png [Привет из Docker!]

Наконец, попробуйте добавить имя к адресу вашего веб-приложения, чтобы проверить другой маршрут, например: + https: /// hello / Sammy +.

изображение: https: //assets.digitalocean.com/articles/godockernginx/step4c.png [Привет, Сэмми!]

Вы создали файл Docker Compose и написали конфигурацию для запуска приложения Go внутри контейнера. В завершение вы перешли на свой домен, чтобы проверить, правильно ли настроен маршрутизатор + gorilla / mux + для запросов к вашему веб-приложению Dockerized Go.

Заключение

Теперь вы успешно развернули веб-приложение Go с помощью Docker и Nginx в Ubuntu 18.04. С Docker обслуживание приложений становится меньше хлопот, потому что среда, в которой выполняется приложение, гарантированно будет одинаковой при каждом запуске. Пакет gorilla/mux содержит отличную документацию и предлагает более сложные функции, такие как именование маршрутов и обслуживание статических файлов. Для большего контроля над модулем сервера Go HTTP, такого как определение пользовательских тайм-аутов, посетите official docs.

Related