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.
- VS Code installed on your machine
- Remote Containers extension installed within VS Code (
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:
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:
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
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:
> email@example.com 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 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..