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 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:
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