In the previous post, you probably ran the following and had no idea what you were doing. If you did, shhhh and move along…
docker image build --build-arg BUILD_IMAGE=mcr.microsoft.com/windows/servercore:1903 --build-arg BASE_IMAGE=mcr.microsoft.com/windows/nanoserver:1903 --tag sitecore-assets:9.2.0-nanoserver-1903 --isolation 'hyperv' .
Some of this is pretty intuitive. Such as the “docker” part. “image” just means you’re working with Images. “build” does what you think. You are building an image with docker. I’m not making it up, folks.
Now things get a little trickier, you notice we are passing the following options:
- Two Build-Args (You can have as many as you want)
- One Tag
- One Isolation level
We’ll talk about Build Args in a sec. Focusing on the Tag Option, that essentially allows you to reference the image later for builds. It’s nothing fancy except it names the repository first, then the image name second. In the example, the repository is “sitecore-assets” and the image is “9.2.0-nanoserver-1903”. Next is the Isolation. This for windows should always be set to “hyperv” because someone who knows a lot more about this said so, and I’m not inclined to argue much with them.
Looking at build-args now, to make sense of them, we’ll want to pop open the Dockerfile itself. The one sitting in \windows\9.2.0\sitecore-assets. When we do open this up, we see the following
# escape=`
ARG BUILD_IMAGE
ARG BASE_IMAGE
FROM $BUILD_IMAGE as build
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# download remote assets
RUN New-Item -Path 'C:\\downloads' -ItemType 'Directory' -Force | Out-Null; `
& curl.exe -sS -L -o c:\\downloads\\nuget.exe https://dist.nuget.org/win-x86-commandline/v5.2.0/nuget.exe; `
& curl.exe -sS -L -o C:\\downloads\\urlrewrite.msi https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi; `
& curl.exe -sS -L -o C:\\downloads\\vc_redist.exe https://aka.ms/vs/15/release/VC_redist.x64.exe; `
& curl.exe -sS -L -o C:\\downloads\\7z-installer.exe https://www.7-zip.org/a/7z1900-x64.exe;
# copy local assets
COPY *.zip C:\\downloads\\
COPY patches\\ c:\\patches\\
# install 7zip
RUN New-Item -Path 'C:\\install\\tools\\bin\\7zip' -ItemType 'Directory' -Force | Out-Null; `
& 'C:\\downloads\\7z-installer.exe' /S /D='C:\\install\\tools\\bin\\7zip\\';
# verify assets
RUN Get-ChildItem -Path 'C:\\downloads\\*.zip' | ForEach-Object { & 'C:\\install\\tools\\bin\\7zip\\7z.exe' t $_.FullName -r }
# install nuget
RUN Move-Item -Path 'C:\\downloads\\nuget.exe' -Destination 'C:\\install\\tools\\bin' -Force;
# install microsoft xdt assembly
RUN & 'C:\\install\\tools\\bin\\nuget.exe' install 'Microsoft.Web.Xdt' -Version '3.0.0' -OutputDirectory 'C:\\install'; `
Copy-Item -Path 'C:\\install\\Microsoft.Web.Xdt*\\lib\\netstandard2.0\\*.dll' -Destination 'C:\\install\\tools\\bin'; `
Remove-Item -Path (Get-Item -Path 'C:\\install\\Microsoft.Web.Xdt*\\').FullName -Recurse -Force;
# extract assets, skip wdps, move already extracted wdps
RUN $zips = Get-ChildItem -Path 'C:\\downloads\\*.zip' -Exclude '*.scwdp.zip'; `
$zips | ForEach-Object { Expand-Archive -Path $_.FullName -DestinationPath 'C:\\packages' -Force; }; `
$zips | ForEach-Object { Remove-Item -Path $_.FullName -Force; }; `
$zips = Get-ChildItem -Path 'C:\\downloads\\*.zip' -Exclude '*Configuration files*.zip'; `
$zips | ForEach-Object { Move-Item -Path $_.FullName -Destination 'C:\\packages'; };
# move installers
RUN New-Item -Path 'C:\\install\\setup' -ItemType 'Directory' -Force | Out-Null; `
Get-ChildItem 'C:\\downloads\\*.*' -Include '*.exe', '*.msi' | Move-Item -Destination 'C:\\install\\setup';
# add tools folder
COPY tools C:\\install\\tools
FROM $BASE_IMAGE
COPY --from=build ["C:\\install\\", "C:\\install\\"]
COPY --from=build ["C:\\packages\\", "C:\\packages\\"]
COPY --from=build ["C:\\patches\\", "C:\\patches\\"]
It’s a bit much, yeah. Let’s eat the elephant one bite at a time, though.
# escape=`
This simply changes the escape character from back slack to back tick. Keep it spicy, guys.
ARG BUILD_IMAGE
ARG BASE_IMAGE
These look sneakily like the Args passed in. HRM! Sure enough, the values from the command line are mapped into here. You can reference them later with a dollar sign, such as $BUILD_IMAGE
FROM $BUILD_IMAGE as build
FROM is a fun one. This guy actually sets a new build stage. Anything run after this is run on that build stage.
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
SHELL does kinda what you think. Commands run after this will use whatever shell is defined here. We like PowerShell, though. From the bottom of our hearts.
RUN New-Item -Path 'C:\\downloads' -ItemType 'Directory' -Force | Out-Null; `
& curl.exe -sS -L -o c:\\downloads\\nuget.exe https://dist.nuget.org/win-x86-commandline/v5.2.0/nuget.exe; `
& curl.exe -sS -L -o C:\\downloads\\urlrewrite.msi https://download.microsoft.com/download/1/2/8/128E2E22-C1B9-44A4-BE2A-5859ED1D4592/rewrite_amd64_en-US.msi; `
& curl.exe -sS -L -o C:\\downloads\\vc_redist.exe https://aka.ms/vs/15/release/VC_redist.x64.exe; `
& curl.exe -sS -L -o C:\\downloads\\7z-installer.exe https://www.7-zip.org/a/7z1900-x64.exe;
RUN does kinda what you think. It executes something in the shell (which is now PowerShell. So it creates a new folder first in the C drive of the Image. Then it uses curl.exe (we love curl, too) to download some files into that directory. Nothing crazy so far, right?
This post is getting pretty intense. Time to:
OK, back on track:
COPY *.zip C:\\downloads\\
COPY patches\\ c:\\patches\\
COPY here is also pretty straight forward. All those zip files we had next to the docker file? They are going in the Image’s C:\downloads now. Same with the folder we had in the local file system called patches. Copy can reference the host’s file system, or even another Image’s file system.
RUN New-Item -Path 'C:\\install\\tools\\bin\\7zip' -ItemType 'Directory' -Force | Out-Null; `
& 'C:\\downloads\\7z-installer.exe' /S /D='C:\\install\\tools\\bin\\7zip\\';
Another RUN, this time to install 7-Zip.
RUN Get-ChildItem -Path 'C:\\downloads\\*.zip' | ForEach-Object { & 'C:\\install\\tools\\bin\\7zip\\7z.exe' t $_.FullName -r }
# install nuget
RUN Move-Item -Path 'C:\\downloads\\nuget.exe' -Destination 'C:\\install\\tools\\bin' -Force;
# install microsoft xdt assembly
RUN & 'C:\\install\\tools\\bin\\nuget.exe' install 'Microsoft.Web.Xdt' -Version '3.0.0' -OutputDirectory 'C:\\install'; `
Copy-Item -Path 'C:\\install\\Microsoft.Web.Xdt*\\lib\\netstandard2.0\\*.dll' -Destination 'C:\\install\\tools\\bin'; `
Remove-Item -Path (Get-Item -Path 'C:\\install\\Microsoft.Web.Xdt*\\').FullName -Recurse -Force;
# extract assets, skip wdps, move already extracted wdps
RUN $zips = Get-ChildItem -Path 'C:\\downloads\\*.zip' -Exclude '*.scwdp.zip'; `
$zips | ForEach-Object { Expand-Archive -Path $_.FullName -DestinationPath 'C:\\packages' -Force; }; `
$zips | ForEach-Object { Remove-Item -Path $_.FullName -Force; }; `
$zips = Get-ChildItem -Path 'C:\\downloads\\*.zip' -Exclude '*Configuration files*.zip'; `
$zips | ForEach-Object { Move-Item -Path $_.FullName -Destination 'C:\\packages'; };
# move installers
RUN New-Item -Path 'C:\\install\\setup' -ItemType 'Directory' -Force | Out-Null; `
Get-ChildItem 'C:\\downloads\\*.*' -Include '*.exe', '*.msi' | Move-Item -Destination 'C:\\install\\setup';
More of the RUN command, just setting up some plumbing and installing utilities that we’ll need later. Again, since we’re layering, all this will be available to downstream images, and we don’t have to jack with it again.
COPY tools C:\\install\\tools
Another simple COPY command to drop off some tools
FROM $BASE_IMAGE
If you remember from earlier, this is going to pop another Image out and the subsequent commands will run against that. All the previous commands are being run against the BUILD Image, which was from servercore. Now we’re running an new internal image from nanocore. I’m assuming this was for some space savings…
COPY --from=build ["C:\\install\\", "C:\\install\\"]
COPY --from=build ["C:\\packages\\", "C:\\packages\\"]
COPY --from=build ["C:\\patches\\", "C:\\patches\\"]
Ah, ha. So what we see here is that the COPY command is grabbing files from the build image (servercore) and copying them over to nancore. Again, hypothesizing this is for space constraints.
If you want to read through all the commands, you can head over to the build reference site.
Now that we understand the basics of a Dockerfile, let’s try to spin up a solr server. Try that out in Part 6: Simply Solr.
This is a post in the “Yet Another Sitecore Docker Series.” Other Posts include
- Part 1: The Beginning
- Part 2: Running Docker
- Part 3: Layers are Yum
- Part 4: Composing an Image
- Part 5: Deconstructing a Dockerfile
- Part 6: Simply Solr
- Part 7: Smooth as SQL
- Part 8: It’s Sitecore Time
- Part 9: Compose all the Things