Let's say we're in an environment where we have a modern CI/CD pipeline for a number of containerized apps. We also have a number legacy apps which haven't been containerized yet.
I'm wondering how sound/unusual/crazy the following idea is: even for apps which don't run in containers in production, use container images and a container registry as a vehicle to deploy binary build artifacts.
Here's a very simple example to illustrate the idea: let's say we have a .NET app which consists of two projects. One that rarely changes and contains a large number of static assets (
ChangesRarely), and another small, lightweight one which changes often (
Now, let's say we're using the following
Dockerfile to build the app in a multi-stage build:
FROM mcr.microsoft.com/dotnet/sdk:3.1 AS builder ADD src src RUN dotnet publish -o buildOutput/ChangesRarely src/ChangesRarely RUN dotnet publish -o buildOutput/ChangesOften src/ChangesOften FROM alpine COPY --from=builder buildOutput/ChangesRarely /buildOutput/ChangesRarely COPY --from=builder buildOutput/ChangesOften /buildOutput/ChangesOften
Note that because of the two separate
COPY instructions, the resulting image will contain two separate layers. This will be important in just a second.
When our CI/CD build system (e.g. GitHub Actions) needs to create a new build, it'll basically run
docker build -t myapp . and push the resulting image to a container registry. So far, pretty standard.
Now let's say we want to deploy a new version to production. Again, "production" isn't some sort of container orchestrator (yet) - assume it's a set of plain old servers in a data center. So here's where the approach might become a tad unusual:
Each production server runs a Docker engine- but only to pull the container image and subsequently copy the build artifacts out of it, deploying them to their final destination (some local folder):
id=$(docker create myapp) # pulls image from container registry, if necessary docker cp $id:/buildOutput - | tar zxf - # copy build artifacts docker rm -v $id # destroy temp container
I've confirmed that this really works. But, why would you do that? Three main reasons:
The container registry acts as a unified store for all build artifacts (for containerized and non-containerized apps). No need to manage two different artifact stores.
Image layers which are identical across builds (such as the large
ChangesRarelylayer in the example above) only need to be stored once in the container registry, preserving storage space
They also will be cached by the production server's Docker engine, preserving network bandwidth and reducing deployment times.
How usual or unusual is this approach?
Any problems with the approach that I might be missing?