Образ YaMDB: создать и запустить
На своём компьютере в корневой директории проекта YaMDB создайте файл Dockerfile и добавьте в него несколько инструкций:
Скопировать кодYAML
# создать образ на основе базового слоя python (там будет ОС и интерпретатор Python)
FROM python:3.8.5
# создать директорию /code
RUN mkdir /code
# скопировать файл requirements.txt из директории, в которой лежит докерфайл, в директорию /code
COPY requirements.txt /code
# выполнить команду (как в терминале, с тем же синтаксисом) для установки пакетов из requirements.txt
RUN pip install -r /code/requirements.txt
# скопировать всё содержимое директории, в которой лежит докерфайл, в директорию /code
COPY . /code
# при старте контейнера выполнить runserver
CMD python /code/manage.py runserver 0:8000
FROM
Инструкция FROM определяет базовый образ, на основе которого создается образ:
Скопировать кодBASH
FROM <image>:<tag>
# <image> — имя базового образа, например ubuntu
# <tag> — необязательный параметр, указывает конкретную версию образа
Если не указать версию образа, то будет установлена последняя версия (и тег latest), но хорошей практикой является явное указание версии.
LABEL
Инструкция LABEL задает служебную информацию об образе, это может быть информация об авторе, о версии (о версии образа, конечно же, не автора), о дате релиза или о числе сломанных клавиатур в процессе работы. Пары «ключ-значение» записываются через пробел, ключи придумывает сам разработчик:
Скопировать кодBASH
LABEL <ключ>=<значение> <ключ>=<значение> ...
Например, LABEL author='praktikum@yandex.ru' version=1 broken_keyboards=5.
COPY
Инструкция COPY копирует файлы и директории из указанной директории в директорию контейнера:
Скопировать кодBASH
COPY <файл/директория> <путь-внутри-контейнера>
# альтернативный вариант записи:
COPY ["<файл/директория>", "<путь-внутри-контейнера>"]
Например, COPY api /app.
Если вы не хотите, чтобы какие-то файлы попали в контейнер, перечислите их в .dockerignore, принцип такой же, как с .gitignore.
RUN
RUN выполняет команды внутри контейнера так, как если бы эти команды выполнялись в терминале. Например, можно вызвать утилиту или просто создать директорию через mkdir. Чтобы эта инструкция работала — base image должен содержать все необходимые утилиты.
Скопировать кодBASH
RUN <команда>
# или, например
RUN ["bash", "myprogram.py", "argument1", "argument"]
ENV
Инструкция ENV задаёт переменные окружения в контейнере:
Скопировать кодBASH
ENV <ключ> <значение>
Например,
ENV DATABASE_NAME yamdb
ENV DATABASE_PORT 5432
Использование ENV — хорошая практика: секретные данные (ключи, пароли, токены) лучше не хранить в коде.
WORKDIR
Инструкция WORKDIR задаёт директорию для выполнения команд, следующих за этой инструкцией; она работает аналогично команде cd в терминале. В инструкции должен быть указан абсолютный путь директории.
Скопировать кодBASH
WORKDIR <путь-внутри-контейнера>
Например, после выполнения инструкции WORKDIR /code/app директорией, из которой в образе исполняются команды, будет назначена /code/app.
Следовательно, команда копирования файлов из папки /project в директорию code/app должна выглядеть не COPY /project /code/app, а лаконичнее: COPY /project .
CMD
Эта инструкция выполняет команду при старте контейнера. Синтаксис команд может быть таким же, как в терминале:
Скопировать кодBASH
CMD <команда>
# или
CMD ["bash", "run.sh"]
Например, команда python manage.py runserver
Время собирать образ
Убедитесь, что вы находитесь в той же директории, где сохранён докерфайл и запустите сборку образа. В команде укажите, как должен называться образ: docker build -t yamdb .. Точка в конце команды — это путь до докерфайла, на основе которого производится сборка.
По окончании сборки запустите контейнер: docker run -it -p 8000:8000 yamdb
Теперь вы можете зайти в браузере на localhost:8000: приложение запущено и работает!
Откройте новое окно терминала и выполните команду docker container ls:
В терминал будет выведена таблица со списком запущенных контейнеров. Сейчас он всего один, но и этого достаточно.
- В колонку
CONTAINER ID выводится уникальное имя контейнера, - в колонку
IMAGE — имя образа, на основе которого создан контейнер, COMMAND — это команда, которая выполнилась в контейнере после сборки,CREATED — когда был создан контейнер,STATUS — состояние контейнера,PORTS — порты контейнера (в вашем случае приложение в контейнере запущено на 8000 порте, и этот же порт «проброшен» наружу: по этому порту можно обратиться к приложению в контейнере),NAMES — человекочитаемое имя контейнера, его можно задать, чтобы обращаться к контейнеру не по CONTAINER ID, а по имени (контейнер можно переименовать командой docker container rename).
Список всех команд, для работы с контейнером можно вызвать через docker container:
Остановите запущенный контейнер: docker container stop <CONTAINER ID>.
Снова выполните docker container ls: контейнер остановлен, список будет пуст.
Выполните ту же команду с ключом -a (all, «все»): вы увидите, что контейнер никуда не делся, просто он неактивен. Запустите его снова, теперь уже не через запуск образа, а обратившись к существующему контейнеру: docker container start <CONTAINER ID>. Откройте приложение в браузере: всё работает, контейнер запущен.
А что внутри контейнера?
В контейнере запущена операционная система, и в ней можно работать через терминал точно так же, как в ОС вашего компьютера или удалённого сервера. Надо войти в запущенный контейнер.
Для входа в контейнер выполните команду docker exec -it <CONTAINER ID> bash.
Для эксперимента создайте в контейнере какой-нибудь файл с помощью команды touch (работа в контейнере не отличается от работы в обычной ОС). После этого покиньте контейнер: выполните команду exit.
Остановите контейнер, затем запустите его снова и проверьте, на месте ли ваш файл.