Dev env using Docker-Compose and VS Code
Recently, I have been experimenting with moving my development environment to a Dockerized version, so that I can move it closer to production. In an effort to get there, I converted my personal project ( mocsh.com ) to a docker-compose based setup using Java 15. Haven't pushed it to production yet, because I'm still playing with it, but I think the development environment has reached a stage that I would say is "mature".
I will walk you through the steps to set up a multi-service ( webapi, db ), and use VS Code to do development inside that. This is going to be agnostic of technology, so whether Java/Python/NodeJS/Ruby/PHP, MongoDB/PostgreSQL/MySQL/MariaDB, or your favourite stack, it should all work.
- you have Docker For Desktop installed on your machine, and it ships with docker-compose
- you are familiar with the basics of docker-compose. In case you are not, here is the official documentation on Getting started with docker-compose
We will do this in a 2 part series, covering the following:
- Part 1 ( this article ) - setup a docker-compose environment for a 2 tier application
- Part 2 - Use VS Code for development within this environment
You can extrapolate / expand this example to as complex an application, but let's get started by creating an empty git repo, so that we can track our progress.
git init -q
Let's start by defining the docker-compose file. For the same of this exercise, I am going to assume that the application that we are going to run is a NodeJS application, running on the latest LTS.
Create a file called
command: ["/bin/bash", "-c", "--", "while true; do sleep 86400; done"]
In this directory, run the command:
docker-compose up -d
You should see messages similar to:
Creating my-dev-env_webapi_1 ... done
my-dev-env would be replaced with the name of the directory you have this file in.
To clean up, run
docker-compose down in the same directory.
Understanding the configuration
Lets walk through the individual entries in this file. First the top level sections:
volumes tells docker-compose that we need storage that will not be part of the container, because containers are supposed to be throwaway-capable. We should be able to bring up new containers whenever we want. But then, where does the "persistent" data go ? It stays on volumes.
In this section, we are defining two volumes to help us retain data beyond the lifetime of the container, one for the code, and another for the home directory.
services is a way to tell docker-compose that this is a "runnable" service, and will have its own container.
The service we have defined is one called
webapi. We have the volumes mounted at the paths specified, and we are specifying that this service should be created from the docker image
node:lts. You can see the available tags for the
node image at: Node image on Docker Hub
One important element here, that is required and important, is
command. It specified the command to run when the container is started. The container stops when this command exits. By default, the
gradle container runs the
gradle command. And, given that we have no code in the container, and we don't intend to run anything automatically, the container would stop.
Experiment with the behaviour by removing this entry, and running the
docker-compose up command again.
Adding the database
Adding a database to this configuration is simple. Assuming we want a MongoDB instance to work with, first step is to look for the volumes that need to be mounted to get the storage to be persistent. You may choose to not have a persistent storage, if this is your throwaway instance, but I'm going to show you the steps to do it.
First, we want the data from the database to be persistent across container creation cycles, in case we want to use a different version of the database. So, we will add another entry to the
volumes section that will look like:
Mind you, the spaces in any yaml file are important. So, ensure that the three entries align.
Next, adding the database itself. For this, lets look at the
How to use this image section on the Docker Hub page of Mongo.
Add the service entry from there to our docker-compose file, but with some modifications:
- we want the volume to be mounted
- we don't want the username/password since this is a private only instance
Add the following under the
services section of the
Don't need to stop the existing containers. Just run the
docker-compose up -d command again, and all the relevant actions will be taken.
You will see something similar to:
Creating volume "my-dev-env_db-data" with default driver
Pulling mongo (mongo:)...
latest: Pulling from library/mongo
Status: Downloaded newer image for mongo:latest
my-dev-env_webapi_1 is up-to-date
Creating my-dev-env_mongo_1 ... done
Great we have a working set of containers created. If you open the Docker Dashboard UI, you will see an entry for
my-dev-env or whatever name you used, and then, when you expand that, you will see the two service containers: webapi and mongo.
This article originally published at: blog.mandraketech.in/dev-environment-using-..
Did you find this article valuable?
Support MandrakeTech Blog by becoming a sponsor. Any amount is appreciated!