- Published on
Using Docker-Compose and a Makefile to Setup Local Test Infrastructure
- Authors
- Name
- Yair Mark
- @yairmark
Docker-compose is awesome when you want to quickly spin up some infrastructure to test something. I often reach for it when testing an app that has multiple different pieces that need to run together for example there is a DB, queue and the app itself which needs all this.
Even in a Kubernetes environment, I find it can still be faster and easier to dev locally using compose.
One issue I ran into today was trying to have a common config you use and version control so that it can be used by others for their local infrastructure. My project structure looks as follows:
.env
.gitignore
makefile
-> app/
-> ...
-> Dockerfile
-> infrastructure/
-> ...
-> testing/
-> docker-compose.yaml
-> deployement/
-> local/
-> data/
-> common/
-> someFile.properties
-> application-1.properties
The .env
file is used by docker-compose
where it substitutes ${SOME_VAR}
in your compose file with the value of that var or command line environment variable as described here.
I use my .gitignore
to ignore any testing infrastructure folders and files that are stored in volumes that are mounted against the local environment's data
directory.
In my compose file I define a section that mounts deployment/local/data
and deployment/local/common
so that my app can write its runtime data to data
and read its config from common
. My compose file looks similar to the below:
version: '3.7'
services:
spring-app-1:
image: someorg/app1
volumes:
- '${DATA_VOLUME_1:?NO_DATA_VOLUME_PROVIDED}:/data/'
- '${COMMON_VOLUME:?NO_COMMON_VOLUME}:/config/'
environment:
- spring.config.location=/config/application-1.properties
queue-1:
image: ibmcom/mq
restart: unless-stopped
ports:
- '1414:1414'
- '9443:9443'
volumes:
- 'qm1data:/mnt/mqm'
environment:
- LICENSE=accept
- MQ_QMGR_NAME=QM1
volumes:
qm1data:
In the above, app-1
uses /data
for any storage-related tasks.
The last issue to sort out with the above setup was how the docker-compose file could be easily run from any dev's machine without having to change anything. I ended up with a makefile that defines a variable pointing to deployment/local
relative to the code root using pwd
. The file with a target to run and stop the test infrastructure is below:
APP_DIRS_ROOT=$(shell pwd)/deployement/local
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
docker-build-app-container: ## Builds the app container
docker build -t someorg/app1:0.1 ./app/ -f ./app/Dockerfile
docker-build-all-containers: docker-build-app-container ## Builds all containers
start-test-infrastructure: docker-build-all-containers ## Runs the docker-compose test infrastructure
docker-compose -f ./infrastructure/testing/docker-compose.yaml up -d
stop-test-infrastructure: local-app-wipe ## Stops the docker-compose test infrastructure
docker-compose -f ./infrastructure/testing/docker-compose.yaml down || true
docker volume prune -f || true
docker network prune -f || true