И уменьшите размер исполняемого файла на ~ 73% в качестве бонуса.

  1. часть: создание сервиса
  2. часть: улучшение сервиса
  3. часть: обновление для Интернета
  4. часть: добавление SSE
  5. часть: простая функциональность внешнего интерфейса javascript
  6. часть: frontend - backend коммуникация
  7. часть: логирование на стороне сервера
  8. часть: вы читаете это прямо сейчас
  9. часть: добавление контейнера базы данных
  10. часть: база данных - служебная связь

Дополнение 1: функции, методы, указатели и интерфейсы
Дополнение 2: связь через веб-сокеты
Дополнение 3: связь через сокеты

Зачем вообще использовать Docker?

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

Используя Docker, вы можете создать для себя аккуратную систему развертывания. И вам все равно, какая система на самом деле работает на конечной машине. Вам нужно, чтобы на машине был запущен Docker. Вы можете легко остановить и запустить несколько программ (несколько служб, если вам нравится эта терминология). Вы можете легко изменить порт для веб-сервера Go, не меняя сам код Go. Вы можете одновременно запускать несколько разных баз данных.

Вы можете многое сделать с помощью Docker, и я советую вам потратить время на его изучение.

Тем из вас, кто не знаком с Docker, я рекомендую книгу Брета Фишера Docker Mastery. Это помогло мне перейти от что, черт возьми, такое Docker к отлично, для чего еще я могу использовать Docker.

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

Подготовить проект

Откройте Goland и создайте новый файл с именем Dockerfile в каталоге вашего проекта. Вставьте код ниже. Эта команда создаст пустое изображение с использованием FROM scratch, а затем скопирует содержимое из каталогов css, html, js и linux.

Но подождите, каталога linux пока нет. Причина в том, что мы не создавали наше программное обеспечение. Мы не делали никаких исполняемых файлов.

Создать исполняемый файл Go

Есть множество способов собрать наше программное обеспечение… как создать этот исполняемый файл. Один из способов - использовать встроенные функции Goland.

Создайте новую конфигурацию, скопировав первую. И в этой новой конфигурации измените четыре вещи:

  1. Имя ... это имя будет использоваться для имени исполняемого файла и должно совпадать с CMD [“/medium_service”], поэтому мы используем medium_service, Goland автоматически добавит _linux к имени файла
  2. Выберите выходной каталог (linux, поскольку мы будем использовать контейнеры linux)
  3. Снимите флажок Запускать после сборки
  4. Установите среду на GOOS=linux

Примечание: определяя GOOS, вы можете создать исполняемый файл для любой системы и любой архитектуры, которая доступна.

Уменьшение исполняемого файла на 73%

Когда вы запустите эту конфигурацию, вы сразу увидите, что в этом каталоге linux появляется новый исполняемый файл. Этот исполняемый файл имеет размер 9,6 МБ, и мы сделаем два приема, чтобы сделать его намного меньше. Сначала добавьте два аргумента инструмента flags-ldflags=”-s -w” в Go, как показано на скриншоте ниже.

Запустите эту конфигурацию еще раз, и вы увидите, что размер исполняемого файла составляет примерно 6,9 МБ, сокращение примерно на 28%. Вторая уловка - использовать любые доступные исполняемые упаковщики. Я использую UPX, и я использую его также в продакшене без каких-либо последствий. С commandupx medium_service_linux размер исполняемого файла сократится примерно до 2,6 МБ, то есть на 73%.

Создать исполняемый файл Go с помощью скрипта

Я предпочитаю использовать другой способ - использовать сценарий, будь то сценарий bash или powershell. Поскольку я использую устройство Apple, ниже вы можете увидеть мой сценарий bash. Этот сценарий называется create.sh и помещается в каталог проекта. Он делает множество вещей.

Сначала он получит имя текущего рабочего каталога с помощью name=${PWD##*/}, затем он обновит все модули (не обязательно, но мне нравится иметь последние версии всех модулей), затем он построит наш исполняемый файл с помощью GOOS=linux go build -ldflags=”-s -w” -o linux/”$name”, а затем перейдет в этот linux, упакуйте исполняемый файл с помощью UPX и выйдите.

После того, как все это будет сделано, он наконец-то что-то сделает с докером. Используя docker rmi -f petrjahoda/”$name”:latest, он удалит все предыдущие изображения, уже созданные ранее, используя docker build -t petrjahoda/”$name”:latest ., он создаст изображение. Эта точка означает, что он будет искать файл Dockerfile в каталоге, в котором выполняется эта команда. И, наконец, он отправит этот образ в Docker Hub с помощью docker push petrjahoda/”$name”:latest. Чтобы эта последняя команда заработала, вам нужно иметь собственный репозиторий и войти в Docker на своем компьютере.

Примечание: не забудьте chmod +x create.sh и удалить предыдущий исполняемый файл с помощью _linux в конце.

Запуск скрипта

Когда вы запускаете этот скрипт, вы видите, что происходит множество вещей (см. Ниже). После того, как все будет сделано, вы сможете найти свой образ в репозитории Docker Hub. В моем случае это здесь.

go: golang.org/x/sys upgrade => v0.0.0–20201223074533–0d417f636930
 Ultimate Packer for eXecutables
 Copyright © 1996–2020
UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
File size Ratio Format Name
 — — — — — — — — — — — — — — — — — — — — — — — — -
 6901760 -> 2630120 38.11% linux/amd64 medium_service
Packed 1 file.
Error: No such image: petrjahoda/medium_service:latest
[+] Building 0.4s (8/8) FINISHED 
 => [internal] load build definition from Dockerfile 0.0s
 => => transferring dockerfile: 135B 0.0s
 => [internal] load .dockerignore 0.0s
 => => transferring context: 2B 0.0s
 => [internal] load build context 0.2s
 => => transferring context: 5.26MB 0.1s
 => [1/4] COPY /css /css 0.0s
 => [2/4] COPY /html html 0.0s
 => [3/4] COPY /js js 0.0s
 => [4/4] COPY /linux / 0.0s
 => exporting to image 0.0s
 => => exporting layers 0.0s
 => => writing image sha256:1df9b9adbc1167cb1fcb1fc66d74cf33964c35530dc04fa4f5434e917bc50a53 0.0s
 => => naming to docker.io/petrjahoda/medium_service:latest 0.0s
The push refers to repository [docker.io/petrjahoda/medium_service]
bc5cf960a3a7: Pushed 
6eec7c2c219c: Pushed 
2038e7a8e302: Pushed 
95541ba72fa1: Pushed 
latest: digest: sha256:4584ba804f99d001a57d84bc85b6624eb8f9ab2b8edc9e226e43e670a0ce51b3 size: 1149

Тестовый запуск службы Go в качестве контейнера Docker

Похоже, мы все сделали правильно. Пора это проверить.

Откройте свой терминал или консоль, либо воспользуйтесь встроенным терминалом Goland и запустите docker run — name medium_service -p 90:81 petrjahoda/medium_service:latest. Это запустит новый контейнер с именем medium_service, сопоставив внутренний порт 81 с внешним портом 90 и использующий уже созданный образ с тегом latest. Когда вы запускаете команду (в моем примере мне пришлось использовать этот порт 82, потому что я использовал его в своем приложении), вы видите журналы из своего приложения.

Откройте браузер и перейдите по адресу http: // localhost: 90. Ваша веб-страница должна быть запущена. Если вы попытаетесь нажать кнопку Запросить данные, вы сразу увидите, что запись была успешно зарегистрирована.

Сделать контейнер Docker работать в фоновом режиме

Чтобы этот докер-контейнер работал постоянно, закройте его, нажав CTRL + C, и удалите, используя docker rm medium_service. Теперь запустите его снова, на этот раз с добавленным параметром -d: docker run — name medium_service -p 90:81 -d petrjahoda/medium_service:latest. Это запустит контейнер и отсоединится от него. Итак, теперь ваша консоль может быть использована или закрыта, а ваш веб-сервер работает в фоновом режиме.

Вы можете проверить работу вашего контейнера, используя docker ps -a, который покажет все ваши не удаленные контейнеры, или используя docker stats (см. Изображение ниже), который будет отслеживать ваши работающие контейнеры в реальном времени. В моем случае запущенных контейнеров больше, наверху medium_service.

ПОЗДРАВЛЯЕМ. У вас есть собственная веб-служба, работающая в контейнере Docker. Каждая часть программного обеспечения работает так, как должна, и в качестве бонуса, используя FROM scratch, мы делаем наш контейнер очень безопасным (но, с другой стороны, вы не можете, например, пинговать ИЗ ВНУТРИ контейнера).

Используя docker image ls, вы можете увидеть, что размер нашего изображения составляет около 5,26 МБ (исполняемый файл Go и все другие файлы).

Бонусная функция

Ниже приведен мой файл create.sh, который я использую в производстве для каждого программного обеспечения. Есть две разные вещи. Сначала вы видите, что он запускает ./update, а в конце есть еще три команды докера.

Причина этого в том, что мне нравится иметь правильную версию своего программного обеспечения, и мне не нужно об этом думать. Итак, в каждом программном обеспечении в main.go у меня есть константа const version = “2020.4.3.14”, и когда служба запускается, мне нравится использовать что-то вроде logInfo(“MAIN”, serviceName+” [“+version+”] starting…”).

Это ./update выполняет две функции. Обновите эту константу и обновите последние три строки кода в create.sh, содержащие версию.

В результате получается, что последний образ докера всегда действительно самый последний, и есть больше образов, так как мое программное обеспечение построено с правильным номером версии. Например, версия 2020.4.3.13 объединяется следующим образом:

  • 2020 год
  • 4 - четвертый квартал года
  • 3 - третий месяц в этом квартале
  • 13 - день месяца

Вы можете увидеть использование этого подхода на примере здесь. Также этот исполняемый файл обновления находится в каталоге проекта.

Резюме

Эта статья помогла вам узнать, как…

  • создать исполняемый файл Go двумя разными способами
  • создать образ Docker и отправить его в Docker Hub
  • запустить образ Docker с разными параметрами
  • запустить образ Docker в фоновом режиме (и проверить журналы)
  • сжать исполняемый файл Go на ~ 73%
  • добавить автоматическое управление версиями в качестве бонуса