Ответ 1
После некоторых исследований и испытаний я обнаружил, что у меня были некоторые недоразумения в отношении срока службы контейнеров Docker. Просто перезагрузка контейнера не заставит Docker использовать новое изображение, когда изображение было перестроено тем временем. Вместо этого Docker извлекает изображение только перед запуском контейнера. Таким образом, состояние после запуска контейнера является постоянным.
Зачем требуется удаление
Поэтому перестройки и перезапуска недостаточно. Я думал, что контейнеры работают как сервис: останавливая службу, делайте свои изменения, перезагружайте ее, и они будут применяться. Это была моя самая большая ошибка.
Поскольку контейнеры постоянны, сначала их нужно удалить, используя docker rm <ContainerName>
. После удаления контейнера вы не можете просто запустить его с помощью docker start
. Это нужно сделать, используя docker run
, который сам использует последнее изображение для создания нового контейнера-экземпляра.
Контейнеры должны быть как можно более независимыми
С этими знаниями понятно, почему хранение данных в контейнерах квалифицируется как плохая практика, и Docker рекомендует тома данных/установка каталогов хостов: поскольку для обновления приложений контейнер должен быть уничтожен, сохраненные данные внутри тоже будут потеряны. Это приводит к дополнительной работе для выключения служб, резервного копирования данных и т.д.
Итак, это умное решение, чтобы полностью исключить эти данные из контейнера: нам не нужно беспокоиться о наших данных, когда он хранится на хосте и контейнере только для самого приложения.
Почему -rf
может не помочь вам
В команде docker run
есть переключатель очистки, называемый -rf
. Это остановит поведение хранения контейнеров докеров навсегда. Используя -rf
, Docker уничтожит контейнер после его выхода. Но этот переключатель имеет две проблемы:
- Docker также удаляет тома без имени, связанного с контейнером, что может убить ваши данные.
- Используя эту опцию, невозможно запустить контейнеры в фоновом режиме с помощью
-d
switch
В то время как переключатель -rf
является хорошим вариантом для сохранения работы во время разработки для быстрых тестов, он менее подходит для производства. Особенно из-за отсутствующего варианта запуска контейнера в фоновом режиме, который в основном требуется.
Как удалить контейнер
Мы можем обойти эти ограничения, просто удалив контейнер:
docker rm --force <ContainerName>
Переключатель --force
(или -f
), который использует SIGKILL для запуска контейнеров. Вместо этого вы также можете остановить контейнер до:
docker stop <ContainerName>
docker rm <ContainerName>
Оба равны. docker stop
также использует SIGTERM. Но с помощью --force
коммутатор сократит ваш script, особенно при использовании серверов CI: docker stop
выдает ошибку, если контейнер не запущен. Это может привести к тому, что Дженкинс и многие другие серверы CI будут считать сборку ошибочно неудачной. Чтобы исправить это, сначала нужно проверить, работает ли контейнер, как в вопросе (см. Переменную containerRunning
).
Полный script для восстановления контейнера Docker
В соответствии с этим новым знанием я исправил свой script следующим образом:
#!/bin/bash
imageName=xx:my-image
containerName=my-container
docker build -t $imageName -f Dockerfile .
echo Delete old container...
docker rm -f $containerName
echo Run new container...
docker run -d -p 5000:5000 --name $containerName $imageName
Это отлично работает:)