Когда выполнять команду в docker compose, а когда в dockerfile?
Я новичок в docker, так что потерпите меня за потенциально глупый вопрос.
Насколько я понял, если я хочу иметь работающий контейнер, а не исполняемый файл, то в конце нужно написать "command". Okey.
Итак, если мне нужен контейнер, обслуживающий приложение django, я должен добавить что-то вроде:
python manage.py runserver 0.0.0.0:8000
Теперь вопрос в следующем: Добавляем ли мы это в конец dockerfile, определяющего образ?
Или мне добавить эту команду в docker compose, который использует образ, вот так?
services:
web:
build: .
command: python manage.py runserver 0.0.0.0:8000
[...]
Вы можете создать sh-файл и запустить его из Dockerfile
boot-strap.sh
python manage.py runserver 0.0.0.0:8007
в Dockerfile:
...
ENTRYPOINT ["sh",".../boot-strap.sh"]
таким образом, вы можете добавить другие команды (например, python manage.py migrate ...)
Если что-то имеет смысл поместить в Dockerfile, то поместите это туда (но не все будет иметь смысл). Подумайте о других способах запуска этого контейнера (docker run
; поместите его в манифест Kubernetes), а также о других средах, в которых его можно запустить (например, когда база данных хранится на другом хосте). Если что-то будет в основном неизменным при каждом запуске контейнера, поместите это в Dockerfile.
В приведенном вами примере образ, который вы создаете, предназначен для приложения Django. Когда бы вы ни запускали образ, независимо от контекста, вы, вероятно, всегда захотите запустить приложение Django, и именно с этой командной строкой. Поэтому поместите в Dockerfile
CMD ./manage.py runserver 0.0.0.0:8000
и не предоставлять команду Compose command:
, docker run
, Kubernetes command:
или другие настройки времени развертывания.
И наоборот, ваше базовое хранилище базы данных будет разным в каждой среде. Поэтому имеет смысл указать расположение базы данных с помощью переменной окружения или другой настройки и включить ее в конфигурацию развертывания.
# in a host development environment
export PGHOST=localhost
pipenv run ./manage.py runserver
# docker-compose.yml
version: '3.8'
services:
db:
image: postgres
app:
build: .
environment:
- PGHOST=db # (not a Dockerfile ENV)
ports:
- '8000:8000'
Единственное заметное исключение в отношении command:
- это если у вас есть образ, который может делать две вещи. Комбинация Django и Celery является хорошим примером этого: обе половины будут использовать большую часть одной и той же кодовой базы, поэтому для запуска Celery worker вам нужно запустить тот же образ, но с другой командой
version: '3.8'
services:
redis:
image: redis
app:
build: .
environment: [REDIS_HOST=redis]
ports: ['8000:8000']
worker:
build: .
environment: [REDIS_HOST=redis]
command: celery worker ...