Pull to refresh

Comments 24

UFO just landed and posted this here

А почему не FROM scratch? Мне казалось, для production сборок всегда советуют этот вариант. Его не удобно просматривать, но для прода вроде самое то.

Всегда считал что alpine лучше scratch, в большинстве случаев, если придется лезть внутрь контейнера для траблшутинга. Тем более что в большинстве случаев scratch vs alpine уже не сильно решает, если использовать container registry близко к проду.
P.S. теоретик ;)

В таком случае лучше уж ubuntu/debian. Потому что у alpine иногда бывают веселые баги, в силу того, что у них не совсем стандартные библиотеки.


Ну, например есть вот это. У меня был случай, когда после коннекта оно просто падало с sigfault и все.

Ну я бы выбирал для себя Ubuntu скорее всего или специальный образ от Google на базе ChromiumOS. Но для Golang и Alpine должна работать хорошо.
UFO just landed and posted this here

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

alpine или scratch все-равно лучше в продакшене. Например если на железном серваке крутится десяток (а то и больше) сервисов по несколько экземпляров.
Да, память относительно не дорога, но и расточительно ей пользоваться ИМХО не стоит.
Тогда запускайте прямо на железе, без ОС. Опять микрооптимизациями занимаетесь
еще можно использовать старый добрый Maven (при помощи специального плагина) в котором вполне изолированно можно забилдить Go приложение (в том числе и мульти-модульное) и к тому же в котором есть много хороших плагинов что бы произвести скажем автоматическое формирование дистрибутива собранного приложения и при этом всё достаточно кросс-платформенно
можно посмотреть что из себя скажем представляет мульти-модульный проект в этом случае сформировав его при помощи одно строчной команды
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 может заменить только значение строковых переменных. Значения констант, к сожалению, не заменит.

Да, спасибо! Почему-то я прям была уверена, что где-то видела пример с константами, но действительно не заработает :) Поправила текст.
Подскажите, а какой подход использовать для загрузки через go get приватных репозиториев, например gitlab || bitbucket?

И как вы на работе вообще задаете переменную 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'ом. А вот если захочется неполные пути потом изменить на полные, это будет, наверное, задача сложнее.
А вот если захочется неполные пути потом изменить на полные, это будет, наверное, задача сложнее.

Вот это точно:)

Спасибо за ответы!
хак с .gitconfig, описанный выше — очень помог в свое время, долго головой бился как через ssh использовать приватный репозиторий.

Столкнулся с другой проблемой, некоторые приватные репозитории нельзя было обновлять в силу архитектурных решения с помощью

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 который отображается в доке используемых сервисов, изменения одного модуля отображается в доке зависимого микросервиса с сохранением версии апдейта.

Как-то так. Решение, возможно, не из лучших, но оно работает, хорошо зарекомендовало на разных серверах и ос.

пытался химичить и как-то использовать известные системы управления зависимостями — но все приводило в Ад.
Подскажите пожалуйста подходящий тул для миграции бд в go, с поддержкой PostgreSQL в идеале, чтобы работала по аналогии liquibase или flyway, в силу привычки использования. А именно чтобы можно было встроить в приложение, автоматическое управление миграцией в кластере инстансов прилжения с локом при миграции и поддержка автоматического поиска новых скриптов в некоторой директории по какому-то паттерну.
Сама я в продакшн пробовала только goose (как раз для PostgreSQL), встроить в приложение можно было, насчет локов точно не скажу, но да, в случае с несколькими инстансами проблем не было.

Вообще, я сейчас (вот прямо сейчас) как раз пишу управление миграциями для reform, но, думаю, пока там всё будет готово к продакшн, пройдет еще какое-то время.

Приходите к нам в русскоязычный слак — slack.golang-ru.com, у нас там есть канал #databases как раз для таких вопросов — может, кто что интересное посоветует из своего опыта.
Спасибо! И спасибо за приглашение!
GOPATH — такой же как и системный PATH, только для go. И точно также, как и в PATH мы указываем НЕСКОЛЬКО каталогов, в ОДНОМ GOPATH можно указать несколько точек входа к рабочим go-пространствам.
Sign up to leave a comment.

Articles