Foundational Overview of the Docker Compose file

What if you could pull together many services easily with some sane defaults and set up your application in just a few lines of code? That’s Docker Compose for you.

No more "Well, it works on my machine" using Docker Compose.

Keeping a team working efficiently can be a challenge when you have an application that has many dependencies and requires specific configuration in order to run correctly. You can install each dependency on your machine, but forgetting one step could give you behavior that’s different from everyone else.  You could create VM with something like Vagrant and that can be possible, but that could put a lot of strain on your computer’s resources and adding a new service is no simple matter. Or you could have a system where running a handful of commands (as little as one) can get you a server up and running, with the right dependencies, and configuration mostly hands free. That’s what Docker Compose can do for you.

Docker Compose is essentially an abstraction on top of Docker where you could orchestrate the building and configuration of one or more containers in just one file. This file is named docker-compose.yml. Here’s an example from the Docker documentation:

				
					version: '3'

services:
  db:
    image: postgres
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
				
			

We’ll break down the docker-compose.yml file soon, but before that I wanted to note something. All you need is that one file and then running the following command and you’ll have a complete application running with it’s dependencies:

				
					docker-compose up
				
			

Yes, that’s it. Just that one command. Docker Compose will do the rest for you. In the example above, what you’ll have in the end is a Django app running on port 8000 with postgres configured (assuming you include the missing Dockerfile stated in the Docker documentation above).

Examining the docker-compose.yml file

Now lets break down the docker-compose.yml file. It’s fairly straightforward once you understand it:

				
					version: '3'
				
			

This denotes the version of docker-compose dialect that you’ll use in the yaml configuration file. Over time, Docker adds to the dialect so specifying the version allows Docker to know if it can or can’t run the directives inside of the yaml file.

				
					services:
				
			

Here you list your containers. It’s best practice to have one container per service (.i.e. mysql by itself, your app by itself, redis by itself, etc). That allows multiple services to interact with each other and you could scale each container by itself. Occasionally there are cases where you’d put more than one service in a container, but it’s highly encouraged to keep it to one service per container.

				
					db:
    image: postgres
				
			

The first key db is the name you want to put for your service. Docker Compose exposes all of the containers to each other so you could reference by their host name and their hostname will be the name you call the service in the compose file. The image key is the base image your container will be based off of. Basically an image is a cookie cutter and a container is the baked cookie. You only need one cookie cutter (image) to make many of the same cookies (containers based off of one image).

				
					build: .
				
			

If you need to build your container in a very specific way and add your own dependencies you have the flexibility of doing that using a Dockerfile. The build key denotes where to find that file. In that Dockerfile you’ll specify the base image you’ll use, say ubunturedis, etc. By default, it pulls images from here, but you could specify your own registry. Say, for instance, you need to install very specific libraries, maybe even compile a program manually, you would use a Dockerfile to delineate all of those steps.

				
					command: python manage.py runserver 0.0.0.0:8000
				
			

If you need to build your container in a very specific way and add your own dependencies you have the flexibility of doing that using a Dockerfile. The build key denotes where to find that file. In that Dockerfile you’ll specify the base image you’ll use, say ubunturedis, etc. By default, it pulls images from here, but you could specify your own registry. Say, for instance, you need to install very specific libraries, maybe even compile a program manually, you would use a Dockerfile to delineate all of those steps.

				
					volumes:
      - .:/code
				
			

This says to mount the local path . to the path /code inside of the container.

				
					ports:
      - "8000:8000"
				
			

This means to forward calls from port 8000 on the host machine to port 8000 in the container. For instance, you could call the web service on your host machine with http://localhost:8000.

				
					depends_on:
      - db
				
			

If you need other services that you depend on like a database you can use depends_on. This will bring up those containers in the listed order, but not specifically wait for them. There’s also the similar links key which waits until the containers listed under links are actually running before it runs.

And there you go, that’s an overview of how easy it is to use Docker Compose to set up your application very easily for you and for others in a repeatable and predictable fashion.

Never miss another post!

Get my latest articles delivered directly to your inbox.

Never miss another post!

Get my latest articles delivered directly to your inbox.

🙏

Great Choice!

Thanks for enabling notifications! Don’t worry, I hate spam too and I won’t ever disclose your contact information to 3rd parties.