How to Use Docker Compose With Virtual Hosts and Shared Services (Like Db) for Dev Environment

Docker as been immensely popular in the past years. If you are not using docker at least in your dev environment in 2017. You are surely missing out on some great advantages.

Your new software engineer should start writing production-ready code in a matter of hours not days. All thanks to docker.

Along the same lines, this post will cover how you can set up docker for your dev environment with least friction and maximum productivity. It is an opinionated post. We migrated to this external_links approach so that we could run multiple projects/microservices that use the same db/services shared among them.

Context

  • This tutorial is generally agnostic of docker and docker-compose versions (I am using docker compose 1 syntax). I assume you have docker and docker-compose installed and know about them.
  • It uses external images like Nginx proxy for virtual host per project. Mysql db as shared external service. It could also have been mongo or redis or even rabbit mq. The main point is to use it as external_links in the docker compose file, so that it can be shared among projects.
  • It uses a demo app which emulates the page visit/hit counter popular decades back with a ~30 liner Nodejs app and Mysql db.
  • I would like to keep the description as concise as possible and in points to make it simple and clear. You should read the code of sample counter project and sample mysql container’s docker-compose.yml well.
  • The goal is to grasp the concepts well and apply it to your current project. For example, you could start with replacing your local mysql install with a docker container.

Problems to solve

  1. After I use docker and docker compose, the web server (nginx/apache etc) of project A takes up port 80 and I can’t run project B on port 80 or have a virtual host for both projects.
  2. When I use my db (mysql/postgres) as a service in my docker compose for project A, It is cumbersome to use the same db for another project as its coupled with project A.
  3. I just want to run my mysql database, import some data and run some queries. I don’t want to run my app for now.

Solution goals

  1. To make services like db etc independent of projects and shared among projects similar to having a local install of mysql with multiple databases.
  2. Multiple projects should be able to run in parallel and each of them will have their own virtual host for easy accessibility.

Steps

  1. Run the Nginx proxy to enable virtual hosts with $ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
  2. Add 127.0.0.1 counter.local.dev to your hosts file (on unix based system it is /etc/hosts file)
  3. Create an empty folder db in your home (~/db), to save your mysql data
  4. Clone mysql repo from here maybe at ~/projects/mysql
  5. In ~/projects/mysql run docker-compose up to run mysql, it will create counter db, counts table with one row.
  6. Clone the sample counter app from here to maybe ~/projects/counter.
  7. In ~/projects/counter run docker-compose up
  8. Then go to http://counter.local.dev on your browser you should see Page visited 1 times, refresh it, it should say Page visited 2 times

Virtual host has been possible in above setup as we ran the nginx proxy and configured VIRTUAL_HOST and VIRTUAL_PORT parameters correctly in the docker-compose.yml of the sample counter project. Mysql was already running before the project even started to run and it was external_links, the IP of the mysql container was automatically added to the /etc/hosts of the counter project container which enabled us to use the host for mysql db as mysql in the connection config we passed to the mysql library.

Steps for running dependent services like nginx proxy, mysql can surely be automated for speed and efficiency.

Takeaways

  1. You can plan a step by step migration like first get your db/queue migrated from local install to docker then the app.
  2. Use external_links for all the services like db/queue/redis/solr anything that needs to be shared among projects.
  3. Use nginx proxy to enable virtual host per project with two simple env variables VIRTUAL_HOST and VIRTUAL_PORT in the project’s docker-compose file. VIRTUAL_PORT is 8080 because application is running on port 8080 and same port is exposed from the dockerfile.
  4. Run all your dependencies before hand and then run docker-compose up on your project(s). Dependencies can be run with docker-compose up -d to put it in the background. You can use docker-compose -f logs to follow logs and check if the service is running fine.
  5. In this way, you can run multiple projects sharing the same db instance and each project can have its own virtual host.
Hope you found this helpful. For more clarity, please read the Dockerfile, docker-compose.yml and index.js of the sample counter project thoroughly.

Originally published at geshan.com.np.