Comments 24
А почему не FROM scratch
? Мне казалось, для production сборок всегда советуют этот вариант. Его не удобно просматривать, но для прода вроде самое то.
FROM scratch
, вот примерно так :)Только если сертификаты надо перегенерить, отдельно разворчаиваем alpine и копируем нужные файлы, но это нечастое действие.
P.S. теоретик ;)
Пожалуй не соглашусь с вами про 400mb. Образ ubuntu:16.04 это 119Mb по показаниям docker images. Плюс есть облегчённые сборки ещё меньшего размера. Вот тут отличная картинка есть с размерами https://hub.docker.com/r/blitznote/debootstrap-amd64/
Понятно, что всё равно больше, чем Alpine (3.6 == 3.97Mb), но всё же не в 100 раз.
P.S. 424Mb наблюдаю у вагрант-коробки trusty 14.04, а вот коробка xenial 16.04 уже 275Mb. Похоже, что были проведены какие-то работы по уменьшению образов.
Да, память относительно не дорога, но и расточительно ей пользоваться ИМХО не стоит.
можно посмотреть что из себя скажем представляет мульти-модульный проект в этом случае сформировав его при помощи одно строчной команды
mvn archetype:generate -B -DarchetypeGroupId=com.igormaznitsa -DarchetypeArtifactId=mvn-golang-hello-multi -DarchetypeVersion=2.1.6 -DgroupId=com.go.test -DartifactId=gohello-multi -Dversion=1.0-SNAPSHOT
который при сборке командой
mvn -Passembly
обрабатывает два модуля и выдает архив с исполняемыми файлами в папке assembly-results/target
Кстати, а сейчас есть какие-то тулзы, позволяющие избавиться от полных путей к репозиториям в импортах?
-X
может заменить только значение строковых переменных. Значения констант, к сожалению, не заменит.
И как вы на работе вообще задаете переменную GOPATH для рабочих проектов, ведь если тоже кидать в дефолтный GOPATH, тогда и импорты будут что-то аля company.gitlab.com/middleware/..., что наверное не лучший вариант. Заказчик может захотеть переехать на другой хостинг исходников и что, потом в коде все импорты заменять или я что-то не понимаю?
Чтобы работать с приватными репозиториями мы добавляем маленький хак в .gitconfig. По умолчанию go get тянет репозитории по http(s), мы подменяем на уровне git эту часть url'а на нужную нам. Наверное, не самое красивое решение, но оно работает. Примеры для github'а и абстрактного bitbucket'а:
[url "git@github.com:"]
insteadOf = https://github.com/
[url "ssh://git@my-secret-bitbucket-url:1234"]
insteadOf = https://my-secret-bitbucket-url/scm
А вот насчет второго вопроса, пожалуй, не всё так просто. У меня всего однажды был похожий случай, когда захотелось переехать на другой хостинг, но я просто пробежалась sed'ом по нужным репозиториям, перегенерила vendor и поправила пути импорта. Ну и путей импорта в коде, по-моему, все-таки не так уж много, как может иногда показаться :)
По поводу второго вопроса, у меня еще вопросик, а как вы смотрите на то, что в каждом проекте будет своя папка /src и GOPATH будет начинаться именно рутовой директории проекта? Тогда в импортах вообще не будет фигурировать часть url с именем хостинга исходников.
Я так делал однажды, но получив некоторый опыт с go понял, что это вообще не лучший способ.
Для себя я вижу пару проблем в случае, когда не используется полный путь импорта:
— если вендорить такой репозиторий в другой проект, то менеджер зависимостей может не разобраться, кто откуда растет и где какую зависимость искать
— в особо редких случаях получившийся путь может совпасть с путем импорта какой-нибудь стандартной библиотеки, и это может быть не очень приятно
Ну и в целом есть ощущение, что от отсутствия полных путей импорта головной боли будет больше, чем от их наличия. В случае, если полные пути импорта заданы, их всегда можно найти/заменить тем же sed'ом. А вот если захочется неполные пути потом изменить на полные, это будет, наверное, задача сложнее.
Столкнулся с другой проблемой, некоторые приватные репозитории нельзя было обновлять в силу архитектурных решения с помощью
go get -u <repo-url>
есть N микросервисов, они используют общие модули (подключаемых код через импорт) из приватного репозитория: jwt авторизация, управление пользователями, данные о микросервисах микросервиса (например сервис емейл рассылки) и т.п. не вдаваясь в подробности.
В общем, возник бизнес-кейс: нужно изменить поведение модуля (части кода который используют многие микросервисы) но таким образом, чтобы обновление было контролируемым.
1. внести изменения в модуль, адаптировать микросервисы которые его используют и сделать большой (огромный) апдейт, что в разы отсрочит введение в продакшн необходимых изменений;
2. обновлять по мере необходимости микросервисы по мере необходимости.
Для удобства отказались от плясков с gopath, много было хлопот
1. создаем в корне проектов ./lib, туда и клонируем все с гита
2. добавили в .gitignore lib
3. сделали скрипт обновления ./lib, и при необходимости запускаем что нужно:
ЗЫ: рабочая директория ./bin/linux
скрипт update-go-lib.sh
Repos=(repoA repoB repoC)
cd ../../lib
for repo in ${Repos[*]}
do
if [ -d $repo ]
then
cd $repo
git pull origin master
cd ..
else
git clone git@bitbucket.org:example/$repo.git
fi
done
все делает 1 команда и размещает нужный код в нужном месте
sh update-go-lib.sh
далее используем библиотеку
package main
import "./lib/repoA"
...
более сложный вариант update-go-lib.sh — использование тегов
Также такой подход сделал возможность более динамично изменять части используемых библиотек под нужды конкретного микросервиса: добавление новых функций, изменение респонса (к примеру) и т.п.,
В результате разработка проходит достаточно плавно и прогнозировано, продукт большой, сервисом много.
похожий подход используем и для документации, каждый модуль может иметь свои ендпоинты и т.п., он содержит api-reference.json который отображается в доке используемых сервисов, изменения одного модуля отображается в доке зависимого микросервиса с сохранением версии апдейта.
Как-то так. Решение, возможно, не из лучших, но оно работает, хорошо зарекомендовало на разных серверах и ос.
пытался химичить и как-то использовать известные системы управления зависимостями — но все приводило в Ад.
Вообще, я сейчас (вот прямо сейчас) как раз пишу управление миграциями для reform, но, думаю, пока там всё будет готово к продакшн, пройдет еще какое-то время.
Приходите к нам в русскоязычный слак — slack.golang-ru.com, у нас там есть канал #databases как раз для таких вопросов — может, кто что интересное посоветует из своего опыта.
Готовим сборку Go-приложения в продакшн