Author: Bjørnar Hagen
Date published: 2024-02-10T23:55:00Z
It goes without saying that the title is a bit of a hyperbole, but I do see a lot of developers using Docker in a bit of a strange way. There’s a Dockerfile/Docker compose file present, but the developers never use it. They run everything 100% locally on the machine, the Dockerfile is just used in the CI/CD pipeline. I think this misses a large point of Docker, let’s get into it.
Preqrequisites
Docker or Podman.
Why use Docker?
An infamous phrase in software development you’ve probably heard before:
“It works on my machine.”
While it’s often used as a joke, this issue is probably more often a real one, stealing unnecessary time and causing headaches. Docker was supposed to solve this problem by making it work on your machine, then shipping your machine to the server/other developers, figuratively of course (or maybe literally?). However, if you don’t use Docker locally, you’re not shipping your guaranteed-to-work machine, you’re still doing things the “old way”, but with extra complexity mixed in.
How to properly use Docker
There are many ways to do this, but here’s my preferred way:
- Create a folder in your project called
docker
. - In this folder, create a
Dockerfile.local
and adocker-compose.local.yml
. - In the
Dockerfile.local
, include the main dependencies like Node:20 or Python:3.8. - In the
docker-compose.yml
, include the services you need, like a database, a backend, and a frontend. Then crucially, include avolumes
section to mount your code into the container. - Now, when you want to run your app, you just run
docker-compose -f docker-compose.local.yml up -d
in thedocker
folder, and you should have a running container. - You can now connect to the container, and install your dependencies, run your tests, and start your app.
With this setup you no longer need to use tools like nvm
, pyenv
, jenv
, etc. No more need to pollute your machine with 5 versions of Node, 3 versions of Python, and 2 versions of Java. The only dependency you need is Docker. This has several benefits; you can easily switch between projects without having to worry about different versions of dependencies, you can easily onboard new developers, and you can easily run your app in CI/CD for more than just production builds.
Example setup
/docker/Dockerfile.local:
Notice how we don’t copy over any files, we’ll mount the code as a volume instead.
/docker/docker-compose.local.yml:
1version: '3.1'
2
3services:
4 name-of-your-service:
5 build:
6 context: .
7 dockerfile: Dockerfile.local
8 ports:
9 - '3000:3000'
10 volumes:
11 - ../:/app # Mount the code into the container
12 tty: true
With this volume
setup, your whole project becomes available inside the container. Any change you do on your local machine is immediately reflected in the container.
Bonus: If you’re using VSCode, you can add a .vscode/launch.json
file to easily launch your application without typing commands in the terminal. Only tested on Linux and MacOS, you might need to get Git Bash for Windows.
1{
2 "configurations": [
3 {
4 "name": "Docker - start container",
5 "command": "docker compose -f ${workspaceFolder}/docker/docker-compose.local.yml up -d",
6 "request": "launch",
7 "type": "node-terminal"
8 },
9 {
10 "name": "Docker - Connect to container",
11 "command": "docker exec -it $(docker ps | grep 'name-of-your-service' | awk '{print $1}') sh -c 'if [ -x /bin/bash ]; then exec /bin/bash; else exec /bin/sh; fi'",
12 "request": "launch",
13 "type": "node-terminal"
14 }
15 ]
16}
End notes
Docker is a very powerful tool, and hopefully this article has shown you how to use it more effectively for your local development environment. If you have any questions or feedback, feel free to reach out to me on X.