Dev Env using docker-compose and VSCode - Part 2

Dev Env using docker-compose and VSCode - Part 2

Continuing from the previous post where we setup a docker-compose file, in this part, we will connect to the environment and do some development.

Remember that just deployed a docker-compose based environment with no code, just a volume, in it.

Prerequisites:

  • VS Code installed on your machine
  • Remote Containers extension installed within VS Code ( ms-vscode-remote.remote-containers )
  • git

Step one: Connecting to the container using VS Code

Most of the hard work done. Use the Remote Container extension to connect to the webapi container. To do that, start with F1, and type Attach to Running Container. On selecting this option, you will see the list of containers running. Select the one that has webapi in its name. The one on my setup reads this: my-dev-env-webapi-1.

After a little bit of "installing" and "preparing", VS Code starts up. Open the folder /usr/src/app. This is the location where we have our webapi-code volume mounted. You are now working inside the container.

Now, when you start the terminal inside VS Code, it is already running inside the container. And the prompt should show you so.

When in the terminal run the following:

cd /usr/src/app
git clone https://github.com/navneetkarnani/nodejs-db-test
cd nodejs-db-test
npm install

This will checkout code that I have written to connect to the mentioned database, and fail if it cannot. To test it, run the following:

npm start

And you should see a failure that the environment variable MONGO_DB is not defined.

Updating the environment

We know that our application would see this in the production environment, and that is why we fail, if it is not available. So, lets update our runtime to have that, and be as close to the production environment as possible.

We can close this window. And go back to the docker-compose.yaml in my-dev-env.

In the services section, under webapi, lets add an environment variable that our app is expecting. The entire webapi section will look like this:

  webapi:
    image: node:lts
    environment:
      - MONGO_DB=mongodb://mongo:27017/test
    volumes:
      - webapi-code:/usr/src/app
      - webapi-root:/root
    command: ["/bin/bash", "-c", "--", "while true; do sleep 86400; done"]

Notice the extra environment section we added. Pointing the MONGO_DB to the host named mongo at port 27017. The name mongo will resolve to the name of the service we used in the docker-compose file for the database. If you have a different name, do change it to the same. Docker will do a DNS lookup internally, so our apps don't need to know the IP addresses.

If you try to resolve this from your host (the machine on which docker is running), this will not resolve. Nor will you be able to connect to this database, because we have not opened up any ports from within the container for the external world. All safe.

Testing the configuration

Then go back and run the docker-compose up -d command.

The console should show:

Recreating my-dev-env_webapi_1 ... done
my-dev-env_mongo_1 is up-to-date

Attach to the container again, using the "Attach to Running Container" action, as before. You may also use the small green button on the bottom left of the VS Code window as a shortcut.

Start the terminal inside VS Code, and then:

cd /usr/src/app/nodejs-db-test
npm start

You should see:

> sample@0.0.0 start /usr/src/app/nodejs-db-test
> node ./bin/www

Connected to database

Multiple coding containers ? Really advanced stuff !!

So, if you wanted multiple containers where you want to code, you could easily extend this to do that. Just make sure the volume mounts are unique / appropriate. eg: you want to add another service named: auth-server that runs on nodejs. Just copy the webapi section and make appropriate changes.

On the VS Code side, there is a small set of steps you will need to remember. Why ? because Remote Container extension, by default, keeps the VS Code settings based on the image used. And, if multiple containers have the same image, you will just keep seeing things overwriting each other, and not understand what is happening.

After a lot of hunting with the documentation, I found that Remote Containers created the same devcontainer files, but automatically, and wired up to use the image name.

The documentation is here, and not very explicit. Look for in this: Named Containers

Here are the steps to make it work for me, your results may vary based on your OS. I am on MacOS, so the Global setting are located under ~/Library/Application Support/Code/User/globalStorage/ms-vscode-remote.remote-containers. When we connect to a container, the configuration is created under the imageConfigs directory. If you want to not use a universal config for the image, because you use the same ( node:lts ) for all your dev containers, but with different directories for checkout / breakpoints, etc, then you need to copy the file from there to nameConfig with the name of the container as the name of the file. I filed an Issue on Github to get some usability improvements.

So, coming back. Here are the steps I ran on my laptop:

cd ~/Library/Application\ Support/Code/User/globalStorage/ms-vscode-remote.remote-containers
cd nameConfig
cp ../imageConfigs/node%3alts.json my-dev-env_webapi_1.json

In Summary

In these two articles, we created a docker-compose file that enabled us to work entirely in a container, with no code locally stored.

As containers, and related technologies mature, new use cases replace old ones, and this one is a great hybrid between running a VNC based environment, vs splitting the load on the server and the client. Plus, the added benefit that the dev environment can look closer to the production one.

This can enable interesting workflows, like doing development on a remote docker host, maybe in a datacenter or on Digital Ocean Referral Link where the memory needs of the application are larger than the one available on the developer laptop.

This article originally published at: blog.mandraketech.in/dev-env-using-docker-c..

Did you find this article valuable?

Support MandrakeTech Blog by becoming a sponsor. Any amount is appreciated!