Для запуска приложения ASP.NET Core я создал файл dockerfile, который создает приложение и копирует исходный код в контейнер, который Git получает с помощью Jenkins. Итак, в моем рабочем пространстве в файле dockerfile я делаю следующее:
WORKDIR /app
COPY src src
Хотя Дженкинс правильно обновляет файлы на моем хосте с помощью Git, Docker не применяет это к моему изображению.
Мой базовый скрипт для сборки:
#!/bin/bash
imageName=xx:my-image
containerName=my-container
docker build -t $imageName -f Dockerfile .
containerRunning=$(docker inspect --format="{{ .State.Running }}" $containerName 2> /dev/null)
if [ "$containerRunning" == "true" ]; then
docker stop $containerName
docker start $containerName
else
docker run -d -p 5000:5000 --name $containerName $imageName
fi
Я пробовал разные вещи, такие как --rm
и --no-cache
параметр, docker run
а также остановку / удаление контейнера до создания нового. Я не уверен, что я здесь делаю не так. Кажется, что докер правильно обновляет изображение, так как вызов COPY src src
приведет к идентификатору уровня и отсутствию вызова кеша:
Step 6 : COPY src src
---> 382ef210d8fd
Каков рекомендуемый способ обновления контейнера?
Мой типичный сценарий: приложение работает на сервере в контейнере Docker. Теперь части приложения обновляются, например, путем изменения файла. Теперь в контейнере должна работать новая версия. Docker, кажется, рекомендует создавать новый образ вместо изменения существующего контейнера, поэтому я думаю, что общий способ восстановления, как и я, верен, но некоторые детали в реализации необходимо улучшить.
Ответы:
После некоторого исследования и тестирования я обнаружил, что у меня есть некоторые недопонимания относительно времени жизни контейнеров Docker. Простой перезапуск контейнера не заставляет Docker использовать новый образ, если тем временем образ был перестроен. Вместо этого Docker получает образ только перед созданием контейнера. Таким образом, состояние после запуска контейнера является постоянным.
Почему требуется удаление
Следовательно, перестройки и перезапуска недостаточно. Я думал, что контейнеры работают как служба: остановите службу, внесите изменения, перезапустите ее, и они будут применены. Это была моя самая большая ошибка.
Поскольку контейнеры являются постоянными, вы должны
docker rm <ContainerName>
сначала удалить их, используя . После того, как контейнер удален, вы не можете просто запустить егоdocker start
. Это нужно сделать с помощьюdocker run
, который сам использует последний образ для создания нового экземпляра контейнера.Контейнеры должны быть максимально независимыми
Обладая этими знаниями, становится понятно, почему хранение данных в контейнерах считается плохой практикой, и Docker рекомендует вместо этого тома данных / монтирование хост-каталогов : поскольку контейнер должен быть уничтожен для обновления приложений, сохраненные данные внутри тоже будут потеряны. Это вызывает дополнительную работу по отключению служб, резервному копированию данных и так далее.
Таким образом, это разумное решение для полного исключения этих данных из контейнера: нам не нужно беспокоиться о наших данных, когда они безопасно хранятся на хосте, а контейнер содержит только само приложение.
Почему
-rf
может тебе не помочьdocker run
Команда имеет Очистите переключатель под названием-rf
. Это остановит поведение докер-контейнеров навсегда. Используя-rf
, Docker уничтожит контейнер после его выхода. Но у этого переключателя есть две проблемы:-d
переключателяХотя
-rf
коммутатор является хорошим вариантом для экономии работы во время разработки для быстрых тестов, он менее подходит для производства. Особенно из-за отсутствия возможности запускать контейнер в фоновом режиме, что в большинстве случаев необходимо.Как снять контейнер
Мы можем обойти эти ограничения, просто удалив контейнер:
Переключатель
--force
(или-f
), который использует SIGKILL для запущенных контейнеров. Вместо этого вы также можете остановить контейнер до:Оба равны.
docker stop
также использует SIGTERM . Но использование--force
переключателя сократит ваш сценарий, особенно при использовании серверов CI:docker stop
выдает ошибку, если контейнер не запущен. Это приведет к тому, что Jenkins и многие другие серверы CI ошибочно будут считать сборку неудачной. Чтобы исправить это, вы должны сначала проверить, работает ли контейнер, как я сделал в вопросе (см.containerRunning
Переменную).Полный скрипт для восстановления контейнера Docker
В соответствии с этими новыми знаниями я исправил свой скрипт следующим образом:
Это отлично работает :)
источник
--force-recreate
вариант на Docker композе похожа на то , что вы описали здесь? И если да, то не стоит ли использовать это решение вместо этого (извините, если этот вопрос глупый, но я докер-нуб ^^)docker-compose
умнее простыхdocker
команд. Я работаю регулярно,docker-compose
обнаружение изменений работает хорошо, поэтому пользуюсь--force-recreate
очень редко. Простоdocker-compose up --build
важно, когда вы создаете собственный образ (build
директива в файле compose) вместо использования образа, например, из концентратора Docker.Всякий раз, когда в dockerfile, compose или requirements вносятся изменения, повторно запускайте его, используя
docker-compose up --build
. Чтобы изображения были перестроены и обновленыисточник
/opt/mysql/data:/var/lib/mysql
?--build
в локальных средах разработки. Скорость, с которой докер повторно копирует файлы, которые в противном случае могли бы предположить, что копирование не требуется, занимает всего пару миллисекунд и сохраняет большое количество моментов WTF.Вы можете запустить
build
конкретную службу, запустив ееdocker-compose up --build <service name>
там, где имя службы должно совпадать с тем, как вы ее вызывали, в файле docker-compose.Пример Предположим, что ваш файл для создания докеров содержит множество служб (приложение .net - база данных - давайте зашифровать ... и т. Д.), И вы хотите обновить только приложение .net, имя которого указано
application
в файле составления докеров. Затем вы можете просто запуститьdocker-compose up --build application
Дополнительные параметры Если вы хотите добавить к своей команде дополнительные параметры, например,
-d
для работы в фоновом режиме, параметр должен быть перед именем службы:docker-compose up --build -d application
источник