Woof, that previous post was a lot. A whole lot to ingest. So now we’ve gone through some pretty basic image creation, we understand some of how the Dockerfile works and honestly, I think we’re ready to rock and roll with some more advanced stuff. Let’s talk solr 🙂

As of this writing, the solr Docker Image is built on three layers:

  1. Windows Nano Server
  2. Open JDK
  3. Sitecore solr

We’ve already downloaded the first image from a previous entry. Here’s a link back in case you missed it. Next up, we’re going to build upon that with the JDK Image, which includes basically downloading and installing JDK, and setting the JAVA_HOME variable. See the contents of the Dockerfile located in \windows\dependencies\sitecore-openjdk:

# escape=`
ARG BUILD_IMAGE
ARG BASE_IMAGE

FROM $BUILD_IMAGE as builder

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ENV JAVA_HOME C:\\ojdkbuild
ENV JAVA_OJDKBUILD_VERSION 1.8.0.191-1
ENV JAVA_OJDKBUILD_ZIP java-1.8.0-openjdk-1.8.0.191-1.b12.ojdkbuild.windows.x86_64.zip

RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; `
    Invoke-WebRequest -Uri $('https://github.com/ojdkbuild/ojdkbuild/releases/download/{0}/{1}' -f $env:JAVA_OJDKBUILD_VERSION, $env:JAVA_OJDKBUILD_ZIP) -UseBasicParsing -OutFile 'ojdkbuild.zip'; `
    Expand-Archive ojdkbuild.zip -DestinationPath C:\; `
    Move-Item -Path ('C:\\{0}' -f ($env:JAVA_OJDKBUILD_ZIP -Replace '.zip', '')) -Destination $env:JAVA_HOME;

FROM $BASE_IMAGE

COPY --from=builder /ojdkbuild /ojdkbuild

ENV JAVA_HOME C:\\ojdkbuild

There’s nothing new in here, aside from the ENV command, which does what you think. It sets an environment variable. We can build this image from the following line:

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-openjdk:8-nanoserver-1903 --isolation 'hyperv' .\windows\dependencies\sitecore-openjdk\

Nothing mystical about that either. But we’re not done yet. We need solr! If you open the Dockerfile at \windows\9.x.x\sitecore-xm-solr, you see much of the same:

# escape=`
ARG BUILD_IMAGE
ARG BASE_IMAGE

FROM $BUILD_IMAGE as builder

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ARG SOLR_VERSION
ARG CORE_NAMES

RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; `
    Invoke-WebRequest -Uri ('https://archive.apache.org/dist/lucene/solr/{0}/solr-{0}.zip' -f $env:SOLR_VERSION) -OutFile 'C:\\solr.zip'; `
    Expand-Archive -Path 'C:\\solr.zip' -DestinationPath 'C:\\temp'; `
    Move-Item -Path 'C:\\temp\\solr-*' -Destination 'C:\\solr';

COPY managed-schema.* C:\\temp\\

RUN New-Item -Path 'C:\\clean' -ItemType Directory | Out-Null; `
    Copy-Item -Path 'C:\\solr\\server\\solr\\*' -Destination 'C:\\clean' -Force -Recurse; `
    $env:CORE_NAMES -split ',' | ForEach-Object { `
        $name = $_.Trim(); `
        Copy-Item -Path 'C:\\clean\\configsets\\_default\\conf' -Destination ('C:\\clean\\{0}\\conf' -f $name) -Recurse -Force; `
        Copy-Item -Path 'C:\\temp\\managed-schema.default' -Destination ('C:\\clean\\{0}\\conf\\managed-schema' -f $name); `
        New-Item -Path ('C:\\clean\\{0}\\core.properties' -f $name) -ItemType File | Out-Null; `
        New-Item -Path ('C:\\clean\\{0}\\data' -f $name) -ItemType Directory | Out-Null; `
    }; `
    Remove-Item -Path 'C:\\clean\\README.txt'; `
    Remove-Item -Path 'C:\\clean\\configsets' -Recurse;

FROM $BASE_IMAGE

USER ContainerAdministrator

COPY --from=builder ["C:\\solr", "C:\\solr"]
COPY --from=builder ["C:\\clean", "C:\\clean"]
COPY --from=builder ["C:\\windows\\system32\\find.exe", "C:\\windows\\system32\\"]

RUN MKDIR c:\\data

ENV SOLR_HOME=c:/data

EXPOSE 8983

COPY Boot.cmd .

CMD Boot.cmd c:\\solr 8983 c:\\clean c:\\data

Oooh! There are a couple new commands in place:

  • USER – This performs the next commands as a specific user. In this case “Administrator”. For an explanation, although brief, of the differences between “Administrator” and “ContainerAdministrator, check this SO article.
  • EXPOSE – This opens a specific port to the host (your machine). This makes sense here since solr runs on port 8983 and you see the Boot.cmd noting as much.
  • CMD – This is like RUN, but it happens when the container starts, rather than during the container creation process. Think of your old command.com or the Startup menu in Windows.

Let’s build this image now:

docker image build --build-arg BUILD_IMAGE=mcr.microsoft.com/windows/servercore:1903 --build-arg BASE_IMAGE=sitecore-openjdk:8-nanoserver-1903 --build-arg SOLR_VERSION='7.5.0' --build-arg CORE_NAMES='sitecore_core_index, sitecore_master_index, sitecore_web_index, sitecore_sxa_master_index, sitecore_sxa_web_index' --tag sitecore-xm-solr:9.2.0-nanoserver-1903 --isolation 'hyperv' .\windows\9.x.x\sitecore-xm-solr\

Whoa, that’s a bit more. One thing to point out about our build-args. Notice that BASE_IMAGE here is the previous image we just created above. This creates a layering that looks like this:

Really wanted something more healthy….

Told you layers were Yum. Let’s view a list of our Images again. Run docker image ls, and you’ll end up with a docker image list of the following quality:

Look mom, solr Images!

Why is this so exciting? First of all, if we want to have another version of solr running, we don’t need to go through the hassle of making another JDK image. We can use the same one as before, just provision another solr image using it as the base. See that flexibility? I knew you’d love it too.

Now that we’ve provisioned a solr image, it’s time to make a container! Whee! Following the Sitecore analogy, we’re going to create an item from our template. It’s time to use another docker command called “run” which essentially will provision a new container. Let’s look at the command and then I’ll explain the parameters:

docker run --publish 44011:8983/tcp --mount type=bind,source=c:/Dev/docker/sitecore/dummy/solr,target=c:/data sitecore-xm-solr:9.2.0-nanoserver-1903
  • Publish – This opens and maps a port. When I request the host port 44011 (in a browser for example) then I need to redirect that port to 8983 for the TCP protocol.
  • Mount – This parameter creates a folder share map between the host and the container. Useful for getting files out of the Container. We’ll talk about the other direction later, though. The Source folder being local, the Target folder being inside the container. Notice the flippy of the slashes. This matters. Also, the Source folder has to exist when you create the container. If it doesn’t, you’ll get an error like “Error response from daemon: invalid mount config for type bind

The last item in that list is the image name “sitecore-xm-solr:9.2.0-nanoserver-1903” which you’ll recognize from the previous docker image build command’s “tag” parameter. All kosher now? When we run that, we’ll see a whole slew of text fly by, which vaguely looks like the starting of solr. You’ll even see the nice solr ASCII logo fly by.

I kinda love they have ASCII art in there. TBT on a Whatever Today Is

Open up a browser now, and head to http://localhost:44011 and you should be greeted with the friendly solr admin screen. Did ya? Good! You have successfully run solr in a container. Now go check the folder that you mounted above. Do you see the indexes in there? If so, then things are looking good! Even cooler, if you watch your powershell window, you’ll see logs streamed right to it:

HttpSolrCall means someone is doing something!

That’s good and all, but…uh what about my command prompt? Hit Crtl+C to break away from the container. Note: this doesn’t stop the actual container. It just gives you control back. In the future, if you append a “-d” flag, it will run in detached mode, aka the background.

Feel free to run a docker container inspect on it, and you’ll notice the following values:

"PortBindings":{
   "8983/tcp":[
      {
         "HostIp":"",
         "HostPort":"44011"
      }
   ]
},
"Mounts":[
   {
      "Type":"bind",
      "Source":"c:\\Dev\\docker\\sitecore\\dummy\\solr",
      "Destination":"c:\\data",
      "Mode":"",
      "RW":true,
      "Propagation":""
   }
],

This confirms both our port binding and our mount. Now let’s delete it.

Wait, what? You heard me, let’s delete this container. After all, it’s easy enough to make it again, right? Right. So how do you delete it? Simple enough, once we find the container Id.

docker container ls

Notice the Container ID on the far left. To delete the container, we can do the following:

docker container stop <Container ID>
docker container rm <Container ID>

Running docker container ls again, you’d notice it’s gone. Yay! But why did we do that? If you also look to the right of the screen above, you’ll see a column called “names” with some random words in there (competent_jepsen). This is the auto-generated name for the container. You can change this, however, and we will!

docker run -d --publish 44011:8983/tcp --mount type=bind,source=c:/Dev/docker/sitecore/dummy/solr,target=c:/data --name solr_xm_920 sitecore-xm-solr:9.2.0-nanoserver-1903

Notice the new “name” parameter. This will allow you to give memorable names to your containers rather than having to auto-generate them or find the fancy container ID. Also, I gave the “-d” parameter so I can get my prompt back. After running that above, you should see the container listed with the new Name specified.

Well that makes more sense.

Now I can reference this container by name, and that name makes sense. I think that about wraps up the solr container. Let’s leave it running and move on to Part 7: Smooth as SQL.

The TL;DR Code

#provision the jdk Image and the Solr image
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-openjdk:8-nanoserver-1903 --isolation 'hyperv' .\windows\dependencies\sitecore-openjdk\
docker image build --build-arg BUILD_IMAGE=mcr.microsoft.com/windows/servercore:1903 --build-arg BASE_IMAGE=sitecore-openjdk:8-nanoserver-1903 --build-arg SOLR_VERSION='7.5.0' --build-arg CORE_NAMES='sitecore_core_index, sitecore_master_index, sitecore_web_index, sitecore_sxa_master_index, sitecore_sxa_web_index' --tag sitecore-xm-solr:9.2.0-nanoserver-1903 --isolation 'hyperv' .\windows\9.x.x\sitecore-xm-solr\
#create a container
docker run -d --publish 44011:8983/tcp --mount type=bind,source=c:/Dev/docker/sitecore/dummy/solr,target=c:/data --name solr_xm_920 sitecore-xm-solr:9.2.0-nanoserver-1903

This is a post in the “Yet Another Sitecore Docker Series.” Other Posts include