Docker on Windows
上QQ阅读APP看书,第一时间看更新

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.

Service discovery in Docker isn't for containers only. A container can access another server on the network using its hostname. You could run your web application in a container, but still have it connected to SQL Server running on a physical machine rather than using a database container.

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
You can explicitly specify the Docker network a container should join when it's created, but on Windows, all containers default to joining the system-created Docker network called nat. The database container and web container are both connected to the nat network, so they can reach each other by the container name.

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.

docker container top shows you information on the processes running inside a container, including memory and CPU.

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.