Официальную документацию надо все же читать, проявив усидчивость. Тогда не будет путаницы в базовых понятиях, из-за которой возникает каша в голове.
Давайте разберемся с инструментами и их предназначением, которые Вы используете:
- Комманда
docker
- это консольный интерфейс (CLI) для работы с Docker
docker build
создает по заданному Dockerfile
образ контейнера
docker tag
присваивает указанному образу указанный тег (опция -t
для build
делает то же самое)
docker pull
скачивает указанный образ из удаленного регистра на текущую машину
docker push
заливает указанный образ в удаленный регистр
docker run
запускает новый контейнер из указанного образа
docker ps
выводит список текущих "бегущих" контейнеров
Команда
docker
не жонглирует файлами, она жонглирует образами и контейнерами, а они от нас абстрагированы Docker'ом, как что-то эфемерное. То есть выполняя комманду
docker pull
Вы не скачиваете образ в ту папку, где выполняете команду, и уж точно не скачиваете какие-либо файлы. Все что Вы делаете этой командой - это скачиваете образ в локальное хранилище Docker'а, дабы Docker daemon мог запустить контейнер на основании этого образа.
Команда
docker-compose
- это уже совсем другая команда. Все что она делает - это читает указанный YAML-манифест и выполняет соответствующие команды Docker. Это всего лишь позволяет декларативно указывать желаемые сценарии при работе с Docker в удобном формате. Но ни команда
docker
, ни
docker-compose
, не предоставляют ничего для того, чтобы транспортировать/обновлять версии Ваших манифестов где-то там. Docker, опять таки, жонглирует образами и контейнерами, не более.
У Вас в манифесте указана директива
build:
. Таким образом
docker-compose
пытается сначала собрать контейнер, вместо того, чтобы просто запустить его из образа.
Касательно совета
docker-compose.yml
под каждый env, все правильно советовали. Именно так это и задумывалось. Вы в манифесте указываете отнюдь не разные окружения (development, production), а набор контейнеров, которые должны бежать в одной связке одной логической единицей (концепция POD'ов). Ничего не запрещает делать и так, как сделали Вы, но это сродни использованию дуршлага в роли миски для еды: сегодня Вы нормально из него наворачиваете пельмени, а завтра супчик в нем уже куда-то не туда утекает.
Воркфлоу в Вашем случае можно организовать следующим образом:
- На dev-машине у Вас один
docker-compose.yml
, согласно которому контейнер перед запуском собирается из сорцов.
- Когда у Вас готова новая версия приложения, Вы его собираете через
docker build
, присваиваете ему номер версии через docker tag
и отправляете в удаленный регистр образов через docker push
.
- На prod-машине у Вас отдельный
docker-compose.yml
в котором указано запускать конкретную версию образа (и никаких build). Новая версия приложения - меняем тег образа в манифесте и перезапускаем контейнеры. При выполнении docker-compose
образ автоматически скачается перед запуском, если его нет локально. Если же Вы обновили образ конкретной версии, которая уже была скачана ранее, то да, нужно выполнить docker pull
перед стартом, дабы скачать новый образ.
Дополнительный совет:
Сборку образа и его заливку в удаленный регистр часто удобно автоматизировать с помощь Makefile'ов.