Connecting to database containers from application containers
Docker has a DNS server built into the platform, which is used by containers for service discovery. I started the NerdDinner database container with an explicit name, and any other containers running in the same Docker network can access this container by its name, in exactly the same way as a web server would access a remote database server by its DNS hostname:
This makes application configuration much simpler than a traditional distributed solution. Every environment will look the same. In development, integration testing, QA, and production, the web container will always connect to a database using the nerd-dinner-db hostname, which is actually running inside a container. The container could be on the same Docker host or a separate machine in a Docker Swarm cluster, and that's transparent to the application.
There's one piece of configuration that could be different for each environment, and that's the SQL Server login credentials. In the NerdDinner database image, I use the same configuration approach I used earlier in this chapter with dockeronwindows/ch03-aspnet-config. I've split the appSettings and connectionStrings sections from Web.config into separate files, and the Docker image bundles those configuration files with default values.
Developers can just run a container from the image and it will use the default database credentials, which match the default credentials built into the NerdDinner database Docker image. In other environments, containers can be run with a volume mount, using configuration files on the host server, which specify different application settings and database connection strings.
This is a simplified approach to security credentials, which I'm using to show how we can make our application more Docker-friendly without changing the code. Keeping credentials in a plain-text file on the server isn't a great way to manage secrets, and I'll look at this again in Chapter 9, Understanding the Security Risks and Benefits of Docker, when I cover security in Docker.
There are some updates to the Dockerfile for NerdDinner in this chapter. I've added a health check and the setup to echo logs out from IIS. I still haven't made any functional changes to the NerdDinner code base, only splitting up the Web.config file and setting the default database connection string to use the SQL Server database container. When I run the web application container now, it will be able to connect to the database container by name and use the SQL Server Express database running in Docker:
docker container run -d -P dockeronwindows/ch03-nerd-dinner-web:2e
When the container starts up, I can now open the website using the container's port, click on the Register link, and create an account:
The Register page queries the ASP.NET membership database, running in the SQL Server container. If the registration page is functioning, then the web application has a working connection to the database. I can verify this in Sqlectron, querying the UserProfile table and seeing the new user row:
I've now separated the SQL Server database from the web application, and each component is running in a lightweight Docker container. On my development laptop, each container uses less than 1% of the host CPU at idle, with the database using 250 MB of memory, and the web server 70 MB.
Containers are light on resources, so there's no penalty in splitting functional units into different containers, then you can scale, deploy, and upgrade these components individually.