Adding a dockerfile stage for all environments
I recently needed to add a certificate copy stage to the Visual Studio generated Dockerfile and I thought it would be simple, just add the stage and I was done. But what I found out was the newly added stage never fired when building the project in debug. This has to do with Visual Studio using additional "global" yaml files when it executes the
docker-compose command. Below we will walk through adding a stage and making sure it fires when building in debug.
Adding a new stage
Using the certificate copy stage from above as an example, I want to make sure this stage fires just after the base stage. So I'll use the
base stage as a starting point:
FROM base AS cert COPY ./*.crt /usr/local/share/ca-certificates/ RUN update-ca-certificates
cert stage above just copies all *.crt files in the current directory to the specific certificate directory for linux and then executes the
update-ca-certificates command to register them.
Now we should be able to run the project in debug and see our new stage included. But what actually happens is the build stops at the
base stage. Why is that?
docker-compose -f "<solution path>\docker-compose.yml" -f "<solution path>\docker-compose.override.yml" -f "<solution path>\obj\Docker\docker-compose.vs.debug.g.yml" -p dockercompose4193079649979835183 --no-ansi up -d
If we look close at the command above we'll see Visual Studio includes a global override file, docker-compose.vs.debug.g.yml, in addition to the project's files. This global override file contains configuration such as volume mounts, environment variables, etc required for debugging in the container. But there is a very specific entry that stops Docker from including our
build: target: base
target entry, tells
docker-compose to stop at the configured stage. So now that we figured out the problem, how do we solve it?
cert stage in debug
Essentially our solution will be to override the global override file. The way we do this is by creating a docker-compose.vs.debug.yml file with the following content:
version: '3.4' services: <project name>: build: target: cert
And we will want to include this file in our docker project by editing the docker-compose.dcproj file.
<Project ...> <ItemGroup> <None Include="docker-compose.vs.debug.yml"> <DependentUpon>docker-compose.yml</DependentUpon> </None> </ItemGroup> </Project>
So now that we've created our new override file specifically targeting our new
cert stage and told the docker project where to find it, our new stage should be included in the build. If we look at the
docker-compose command again, we should see our new file included at the end and our
cert stage included in the Docker output window.
docker-compose -f "<solution path>\docker-compose.yml" -f "<solution path>\docker-compose.override.yml" -f "<solution path>\obj\Docker\docker-compose.vs.debug.g.yml" -f "<solution path>\docker-compose.vs.debug.yml" -p dockercompose4193079649979835183 --no-ansi up -d