Docker для разработки Go с горячей перезагрузкой



Книга Docker для разработки Go с горячей перезагрузкой

Создание модуля Go


В Go 1.13 были введены модули. Это означает, что больше не нужно размещать все проекты в одно рабочее пространство Go.


Для начала создаем новый каталог go-docker, в котором будут храниться все файлы.


Затем инициализируем репозиторий Git и создаем модуль Go.


git init
git remote add origin [email protected]:Dirk94/go-docker.git
go mod init github.com/dirk94/go-docker

В директории находится файл go.mod, который содержит все зависимости этого модуля, аналогично файлу package.json в разработке Node.


Создание API


Модуль установлен, пришло время для создания API.


Мы будем использовать пакет маршрутизации thegorilla/mux для API.


go get -u github.com/gorilla/mux

После выполнения команда добавится в качестве зависимости в файл go.mod.


Затем создаем основной файл Go commands/runserver.go.


package main

import (
"fmt"
"github.com/gorilla/mux"
"net/http"
)

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

r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to this life-changing API.")
})

fmt.Println("Server listening!")
http.ListenAndServe(":80", r)
}

Все, что делает API — это возвращает сообщение “Welcome to this life-changing API”.


Проверим, работает ли программа перед тем, как перейти к контейнерам Docker. Для запуска сервера используем команду go run.


go run commands/runserver.go
Server listening!


API работает! ?


Установка Docker


Начнем с создания образа Docker для этого проекта, который содержит набор инструкций, сообщающих Docker, какую среду нужно создать.


FROM golang:latest

WORKDIR /app

COPY ./ /app

RUN go mod download

ENTRYPOINT go run commands/runserver.go

Используем образ golang:latest в качестве основы для этого нового пользовательского образа.


Копируем весь проект в директорию образа /app, а затем загружаем зависимости с помощью go mod download.


И, наконец, сообщаем Docker о запуске команды go run commands/runserver.go.


Для создания этого образа запускаем следующую команду:


docker build -t go-docker-image .

Теперь у нас есть инструкции по созданию образа Docker, которые необходимо запустить.


docker run go-docker-image
Server listening!

Сервер выполняет прослушивание в контейнере Docker, однако при переходе на localhost в браузере появляется сообщение об ошибке “Refused to connect”.



Происходит следующее: контейнер Docker прослушивает порт 80 на предмет входящих запросов, а операционная система хоста — нет. Таким образом, при отправке запроса GET на localhost он не находит работающий сервер.


Ниже представлена диаграмма с описанием проблемы:



Чтобы это исправить, нужно сопоставить порт 80 контейнеров с портом 80 хоста.


docker run -p 80:80 go-docker-image

Диаграмма теперь будет выглядеть следующим образом:



Теперь при переходе на localhost появляется сообщение “Welcome to this life-changing API”!


Изменение исходного кода


Нам необходимо внести некоторые изменения в API.


package main

import (
"fmt"
"github.com/gorilla/mux"
"net/http"
)

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

r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to this life-changing API.
Its the best API, its true, all other API's are fake.")
})

fmt.Println("Server listening!")
http.ListenAndServe(":80", r)
}

Добавляем новую строку в API. Попробуем запустить новый контейнер Docker.


docker run -p 80:80 go-docker-image

Но при переходе на localhost мы видим то же самое сообщение.



Причина заключается в том, что образ Docker не изменился. Чтобы изменения вступили в силу, нам нужно перестроить образ.


docker build -t go-docker-image .
docker run -p 80:80 go-docker-image

Теперь появляется обновленное сообщение:



Установка горячей перезагрузки


Перестройка образа Docker после каждого изменения исходного кода отнимает слишком много времени, поэтому мы создадим более удобную систему.


Мы будем использовать пакет Compile Daemon, который автоматически перестроит и перезапустит приложение Go при изменении любого из исходных файлов Go.


FROM golang:latest

WORKDIR /app

COPY ./ /app

RUN go mod download

RUN go get github.com/githubnemo/CompileDaemon

ENTRYPOINT CompileDaemon --build="go build commands/runserver.go" --command=./runserver

Обновляем Dockerfile, чтобы загрузить пакет CompileDaemon.


Затем изменяем точку входа, чтобы запустить программу CompileDaemon. Указываем команду сборки и запуска программы, которые выполняются при каждом изменении файла Go.


Образ перестраивается при запуске:


docker build -t go-docker-image .

При запуске Docker добавляем флаг -v ~/projects/go-docker:/app. Он устанавливает директорию хоста go-docker в директорию /app контейнера Docker.


При каждом изменении в директории go-docker файлы в директории контейнера /app также изменяются.


Последняя команда представлена ниже. Обратите внимание, что путь -v не может быть относительным.


docker run -v ~/projects/go-docker:/app -p 80:80 go-docker-image

Во время запуска контейнера внесите изменения в исходный код, и вы увидите, что он автоматически обновляется. ??


Использование Docker compose


Сейчас нам приходится писать очень длинную команду docker run -v ~/projects/go-docker:/app -p 80:80 go-docker-image для запуска контейнера.


Эта задача выполнима в подобном проекте, поскольку он содержит только один контейнер. Но предположим, что в проекте есть несколько контейнеров, которые нужно запустить. Выполнение всех команд docker run отнимет очень много сил.


Решение — Docker Compose. С помощью этого инструмента можно указать, какие контейнеры нужно запускать при запуске команды docker-compose.


Для установки создаем файл docker-compose.yml.


version: "3"
services:
go-docker-image:
build: ./
ports:
- '80:80'
volumes:
- ./:/app

Здесь указываем, что нужно создать образ go-docker-image. Образ должен быть собран с использованием Dockerfile в директории ./.


Сопоставляем порты и устанавливаем громкость — на этот раз можно использовать относительный путь.


Для запуска контейнеров, указанных в файле docker-compose.yml, запускаем docker-compose up.


Вот и все! Мы создали рабочий API в Docker, который автоматически перезагружается при изменении файлов! ?


Исходный код можно просмотреть здесь — https://github.com/dirk94/go-docker


528   0  

Comments

    Ничего не найдено.