While developing application and using docker-compose one question quickly arise:
How to properly rebuild application?
Once an image is built new one will not be built with the same tag as long it exists in a local cache.
The compose builds an image it names it with the pattern <context>_<service_name>:latest
.
Where:
- Context is directory name where compose YAML is
- Service is service name in compose YAML file
This means that you can stop or takedown the compose application, next time you run it your images will not be rebuilt if they already exist. Anyway, we aim to rebuild/restart only parts of the system that are changed. Once the compose application is running, we only rebuild the service we are working on.
Let’s look at compose application we used previously in previous post about docker-compose
version: "3.9"
services:
app:
container_name: echo
build: .
ports:
- 9999:9999
volumes:
- ./configs:/app/configs
depends_on:
- liquibase_pg
restart: always
liquibase_pg:
container_name: pg_updater
image: liquibase/liquibase:4.7.0
volumes:
- ./liquibase:/liquibase/changelog
command: liquibase --url="jdbc:postgresql://pg:5432/docker" --changeLogFile=./changelog/changelog.xml --username=root --password=password update
depends_on:
- pg
pg:
container_name: pg
image: postgres:13.1
healthcheck:
test: pg_isready -q -d $$POSTGRES_DB -U $$POSTGRES_USER
timeout: 45s
interval: 10s
retries: 10
restart: always
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: password
POSTGRES_DB: docker
volumes:
- ./db:/docker-entrypoint-initdb.d/
ports:
- 5432:5432
In the above example the compose builds three images:
- dc-playgroud_app
- liquibase/liquibase
- postgres
Only the first time the compose application is started those images will be built. The service app is one I’m working on and if I change code I would like the image to be rebuilt and service restarted. As well it would be nice not to restart its dependencies.
In short, I expect only the service app
to be rebuilt and restarted when I change the code. This is a two-step process:
- rebuild image:
docker-compose build --no-cache app
- rebuild container:
docker-compose up --build --force-recreate --no-deps -d app
When rebuilding an image: do not cache(–no-cache) layers. Then start it up, but first build(–build) container and then recreate it(–force-recreate) if it exists. As well do not restart dependencies(–no-deps).
Instead of running two commands add a Makefile like this:
.PHONY: restart
restart:
docker-compose build --no-cache $(APP) $(APP)
docker-compose up --build --force-recreate --no-deps -d $(APP)
Then from CLI you can run: make restart APP=app