Когда выполнять команду в 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 ...
Вернуться на верх