Using volumes for configuration and state

Application state is an important consideration when you're running applications in containers. Containers can be long-running, but they are not intended to be permanent. One of the biggest advantages with containers over traditional compute models is that you can easily replace them, and it only takes a few seconds to do so. When you have a new feature to deploy, or a security vulnerability to patch, you just build and test an upgraded image, stop the old container, and start a replacement from the new image.

Volumes let you manage that upgrade process by keeping your data separate from your application container. I'll demonstrate this with a simple web application that stores the hit count for a page in a text file; each time you browse to the page, the site increments the count.

The Dockerfile for the dockeronwindows/ch02-hitcount-website image uses multi-stage builds, compiling the application using the microsoft/dotnet image, and packaging the final app using microsoft/aspnetcore as the base:

# escape=`
FROM microsoft/dotnet:2.2-sdk-nanoserver-1809 AS builder

WORKDIR C:src
COPY src .

USER ContainerAdministrator
RUN dotnet restore && dotnet publish

# app image
FROM microsoft/dotnet:2.2-aspnetcore-runtime-nanoserver-1809

EXPOSE 80
WORKDIR C:dotnetapp
RUN mkdir app-state

CMD ["dotnet", "HitCountWebApp.dll"]
COPY --from=builder C:srcinDebug etcoreapp2.2publish .

In the Dockerfile I create an empty directory at C:dotnetappapp-state, which is where the application will store the hit count in a text file. I've built the first version of the app into an image with the 2e-v1 tag:

docker image build --tag dockeronwindows/ch02-hitcount-website:2e-v1 .

I'll create a directory on the host to use for the container's state, and run a container that mounts the application state directory from a directory on the host:

mkdir C:app-state

docker container run -d --publish-all `
-v C:app-state:C:dotnetappapp-state `
--name appv1 `
dockeronwindows/ch02-hitcount-website:2e-v1

The publish-all option tells Docker to publish all the exposed ports from the container image to random ports on the host. This is a quick option for testing containers in a local environment, as Docker will assign a free port from the host and you don't need to worry about which ports are already in use by other containers. You find out the ports a container has published with the container port command:

> docker container port appv1
80/tcp -> 0.0.0.0:51377

I can browse to the site at http://localhost:51377. When I refresh the page a few times, I'll see the hit count increasing:

Now, when I have an upgraded version of the app to deploy, I can package it into a new image tagged with 2e-v2. When the image is ready, I can stop the old container and start a new one using the same volume mapping:

PS> docker container stop appv1
appv1

PS> docker container run -d --publish-all `
-v C:app-state:C:dotnetappapp-state `
--name appv2 `
dockeronwindows/ch02-hitcount-website:2e-v2

db8a39ba7af43be04b02d4ea5d9e646c87902594c26a62168c9f8bf912188b62

The volume containing the application state gets reused, so the new version will continue using the saved state from the old version. I have a new container with a new published port. When I fetch the port and browse to it for the first time, I see the updated UI with an attractive icon, but the hit count is carried forward from version 1:

Application state can have structural changes between versions, which is something you will need to manage yourself. The Docker image for the open source Git server, GitLab, is a good example of this. The state is stored in a database on a volume, and when you upgrade to a new version, the app checks the database and runs upgrade scripts if needed.

Application configuration is another way to make use of volume mounts. You can ship your application with a default configuration set built into the image, but users can override the base configuration with their own files using a mount.

You'll see these techniques put to good use in the next chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.146.37.250