Comments 10
Про alpine - спорно. Нужно делать контейнеры как можно меньше, это уменьшает место для хранения (капитан очевидность), а также сокращает время запуска (привет nvidia с их 5 гиговыми образами).
Я бы рекомендовал делать multistage-билды, чтобы исключить лишние библиотеки и опять же сократить размер образа
Обязательно очищать образ после использования apt-get update
Использовать пользователя для запуска процессов контейнера
Про уменьшение размера- это уменьшение зависимостей, а соотвественно, уменьшение количества уязвимых компонентов на борту образа. Добавлю, что перед сборкой образа мы проверяем зависимости кода через owasp dependency checker, а в самом репозитории уже с помощью snyk. Если что-то выше уровня medium, то чешем репу и обновляем компоненты.
Про не хранить образы на docker hub: с платной подпиской многие компании используют их приватные репы. Там snyk из коробки и возможность автосборки простых образов из gitlab и bitbucket, а также не нужно сопровождать свою инфраструктуру.
Спасибо за разумные дополнения. Плюсанул.
Alpine для питона не стоит использовать - https://habr.com/ru/post/486202/
Так же есть сценарий, что под альпин будут пропущены бинарные зависимости, для того же pydantic
Именно поэтому я и написал в статье то, что написал. Нынче на PyCon был доклад по поводу alpine. И там на примере pydantic было показано, что не стоит.
Спасибо за замечание и участие.
Я бы не был так категоричен: для ml - мы тоже используем стандартные образы от nvidia, а вот, всякие django и flask обязательно на alpine. Поэтому правы тут все)
Это проблема именно poetry; под pip тянется wheel. poetry вообще всё под alpine устанавливает из исходников - там баг в поиске правильных колёс. Но его починят в 1.2.
ый урок и оставленную в тезисах для запоминания ссылку на принцип единственной ответственности. При использовании точки входа процесс создания образа отделяется от слоя запуска сервиса и сервисных функций. При изменении списка входных команд мы не будем трогать dockerfile, и как следствие, нам не придётся во время локальной работы пересобирать сам образ.
всё равно не понял для чего конкретно этот код в entrypoint.sh. Разве явное не лучше неявного? По мне так entrypoint создан немного для другого — инициализация там всякая или предварительная проверка и ожидание доступности необходимых сервисов.
Думаю удобнее не прописывать значения переменных окружения прям в docker-compose. Если их оставить там без значений, то они будут проброщены с хоста или с файла .env
Это как вам будет угодно. Думаю, здесь никаких железобетонных правил нет. По большому счёту, смысл всего остального не меняется — используете вы мой вариант или ваш. Лично я не люблю .env
, использую его редко. Не люблю из-за появляющихся через полгода-год test.env
, test2.env
, stage.env
и т. д. Мне удобнее сразу в docker-compose энвы наблюдать и переопределять их в override
.
----
Что касается второй части комментария, то мой ответ сильно зависит от того, что именно вы предлагаете взамен. Предположу, что CMD
с некой дефолтной командой без использования docker-entrypoint.sh
и аналогичным docker-compose.yml
, где вместо моих command
будет что-то вроде: command: "python <api/consumer>.py"
.
создан немного для другого — инициализация там всякая или предварительная проверка и ожидание доступности необходимых сервисов
Да. Видел, что для этого его в основном и используют, тут с вами не поспоришь. И я, признаться, не знаю, есть ли где-то скрижали, запрещающие иное предназначение.
Свой вариант я предложил отчасти из эксперимента, отчасти из эстетических соображений (увидел в одной компании, проникся, стал использовать) и отчасти из соображений некой абстракции, о которой в уроке, к сожалению, не упомянул. Пожертвовал ради упрощения, как и многим другим.
В общем, можно определить только сервис:
service:
container_name: python-garden_service
image: python_garden
build:
context: .
environment:
PYTHONUNBUFFERED: 1
SERVICE_DB_HOST: service_db
SERVICE_DB_NAME: postgres
SERVICE_DB_USERNAME: postgres
EVENT_BROKER_HOST: mq
EVENT_BROKER_PORT: 5672
EVENT_BROKER_USERNAME: python_garden
volumes:
- .:/opt/lesson_2
Эта конфигурация послужит точкой входа вообще для любых команд. То есть вы можете через docker-compose run
запускать оба инстанса и пробрасывать любую другую допустимую команду:
docker-compose run --rm service api
docker-compose run --rm service consumer
docker-compose run --rm service tests
docker-compose run --rm service bash ...
# et cetera
В этом случае docker-entrypoint.sh
становится сугубо декларативным элементом.
В моём подходе имеется дублирование смыслов, согласен. То есть я объявляю типы запуска одновременно и в docker-entrypoint.sh
, и в docker-compose.yml
, что является избыточным.
[Python Intermediate] Урок 2. Docker и docker-compose