Skip to main content

Adobe

Running AEM Author, Publisher, and Dispatcher Within Docker

Run AEM In Docker

About eight years ago, I was introduced to Docker during a meetup at a restaurant with a coworker. He was so engrossed in discussing the Docker engine and containers that he barely touched the hors d’oeuvres. I was skeptical. 

I was familiar with Virtual Machines (VMs) and appreciated the convenience of setting up application servers without worrying about hardware. I wanted to know what advantages Docker could offer that VMs couldn’t. He explained that instead of virtualizing the entire computer, Docker only virtualizes the OS, making containers much slimmer than their VM counterparts. Each container shares the host OS kernel and often binaries and libraries. 

Curious, I wondered how AEM would perform inside Docker—a Java application running within the Java Virtual Machine, inside a Docker container, all on top of a desktop PC. I expected the performance to be terrible. Surprisingly, the performance was comparable to running AEM directly on my desktop PC. In hindsight, this should not have been surprising. The Docker container shared my desktop PC’s kernel, RAM, CPUs, storage, and network allowing the container to behave like a native application. 

I’ve been using Docker for my local AEM development ever since. I love how I can quickly spin up a new author, publish, or dispatch environment whenever I need it and just as easily tear it down. Switching to a new laptop or PC is a breeze — I don’t have to worry about installing the correct version of Java or other dependencies to get AEM up and running. 

In this blog, we’ll discuss running AEM author, publisher, and dispatcher within Docker and the setup process.

Setup Requirements

The AEM SDK, which includes the Quickstart JAR and Dispatcher tools, is necessary for this setup.  Additionally, Apache Maven must be installed. For the Graphical User Interface, we will use Rancher Desktop by SUSE, which operates on top of Docker’s command-line tools.  While the Docker engine itself is open source, Docker Desktop, the GUI distributed by Docker, is not. 

Step One: Installing Rancher Desktop

Download and Install Rancher Desktop by SUSE. Installing Racker Desktop will provide the Docker CLI (command line interface). If you wish to install the Docker CLI without Rancher Desktop, run the following command:

Windows

Install WinGet via the Microsoft store.

winget install --id=Docker.DockerCLI -e

Mac

Install Homebrew: 

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh) 

brew cask install docker

Step Two: Creating the “AEM in Docker” folder

Create a folder named “aem-in-docker”.  Unzip the contents of the AEM SDK into this folder.  Copy your AEM “license.properties” file to this directory. 

Step Three: Creating the subfolders to contain the Docker Image instructions

Make three subfolders within your “aem-in-docker” folder named “base”, “author”, and “publish”. 

Your “aem-in-docker” folder should look something like this: 

AEM-In-Docker Folder

Step Four: Creating the Base Docker Image instruction (Dockerfile)

Create a file named “Dockerfile” within the “base” subdirectory.

Ensure the file does not have an extension.  Set the contents of the file to the following:

FROM ubuntu
# Setting the working directory
WORKDIR /opt/aem
# Copy the license file
COPY license.properties .
# Copy Quickstart jar file
COPY aem-sdk-quickstart-2024.8.17465.20240813T175259Z-240800.jar cq-quickstart.jar
# Install Java, Vim, and Wget.  Install Dynamic Media dependencies.
RUN apt-get update && \
    apt-get install -y curl && \
    apt-get install -y software-properties-common && \
    add-apt-repository ppa:openjdk-r/ppa && \
    apt-get update && \
    apt-get install -y openjdk-11-jdk vim ca-certificates gnupg wget imagemagick ffmpeg fontconfig expat freetype2-demos
# Unack the Jar file
RUN java -jar cq-quickstart.jar -unpack
# Set the LD_LIBRARY_PATH environmental variable
ENV LD_LIBRARY_PATH=/usr/local/lib

This file directs Docker to build a new image using the official Ubuntu image as a base. It specifies the working directory, copies the license file and the quickstart file into the image (note that your quickstart file might have a different name), installs additional packages (like Java, Vim, Wget, and some Dynamic Media dependencies), unpacks the quickstart file, and sets some environment variables.

Step Five: Create the Base Docker Image

Run the following command from within the “aem-in-docker” folder.

docker build -f base/Dockerfile -t aem-base .

It should take a few minutes to run. After the command has been completed run:

docker image ls

You should see your newly created “aem-base” image.

AEM Base Image

Step Six: Creating the Author Docker Image instruction (Dockerfile)

Create a file named “Dockerfile” within the “author” subdirectory.

Set the contents of the file to the following:

# Use the previously created aem-base
FROM aem-base

# Expose AEM author in port 4502 and debug on port 5005
EXPOSE 4502
EXPOSE 5005
VOLUME ["/opt/aem/crx-quickstart/logs"]
# Make the container always start in Author mode with Port 4502.  Add additional switches to support JAVA 11: https://experienceleague.adobe.com/en/docs/experience-manager-65/content/implementing/deploying/deploying/custom-standalone-install.  Add the Dynamic Media runmode.
ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005", "-XX:+UseParallelGC", "--add-opens=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED", "--add-opens=java.base/sun.net.www.protocol.jrt=ALL-UNNAMED", "--add-opens=java.naming/javax.naming.spi=ALL-UNNAMED", "--add-opens=java.xml/com.sun.org.apache.xerces.internal.dom=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED", "--add-opens=java.base/java.net=ALL-UNNAMED", "-Dnashorn.args=--no-deprecation-warning", "-jar", "cq-quickstart.jar", "-Dsling.run.modes=author,dynamicmedia_scene7", "-p", "4502", "-nointeractive"]

This file instructs Docker to create a new image based on the “aem-base” image. It makes ports 4502 and 5005 available (5005 for debugging purposes), sets up a mount point at “/opt/aem/crx-quickstart/logs”, and specifies the command to run when the image is executed.

Step Seven: Create the Author Docker Image

Run the following command from within the “aem-in-docker” folder.

docker build -f author/Dockerfile -t aem-author .

After the command has been completed run:

docker image ls

You should see your newly created “aem-author” image.

AEM Author Image

Step Eight: Creating the Publisher Docker Image instruction (Dockerfile)

Create a file named “Dockerfile” within the “publish” subdirectory.

Set the contents of the file to the following:

# Use the previously created aem-base
FROM aem-base
# Expose AEM publish in port 4503 and debug on port 5006
EXPOSE 4503
EXPOSE 5006
VOLUME ["/opt/aem/crx-quickstart/logs"]
# Make the container always start in Author mode with Port 4503.  Add additional switches to support JAVA 11: https://experienceleague.adobe.com/en/docs/experience-manager-65/content/implementing/deploying/deploying/custom-standalone-install.  Add the Dynamic Media runmode.
ENTRYPOINT ["java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5006", "-XX:+UseParallelGC", "--add-opens=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED", "--add-opens=java.base/sun.net.www.protocol.jrt=ALL-UNNAMED", "--add-opens=java.naming/javax.naming.spi=ALL-UNNAMED", "--add-opens=java.xml/com.sun.org.apache.xerces.internal.dom=ALL-UNNAMED", "--add-opens=java.base/java.lang=ALL-UNNAMED", "--add-opens=java.base/jdk.internal.loader=ALL-UNNAMED", "--add-opens=java.base/java.net=ALL-UNNAMED", "-Dnashorn.args=--no-deprecation-warning", "-jar", "cq-quickstart.jar", "-Dsling.run.modes=publish,dynamicmedia_scene7", "-p", "4503", "-nointeractive"]

Step Nine: Create the Publisher Docker Image

Run the following command from within the “aem-in-docker” folder.

docker build -f publish/Dockerfile -t aem-publish .

After the command has been completed run:

docker image ls

You should see your newly created “aem-publish” image.

AEM Publish Image

Step Ten: Create the Adobe Network

Let’s set up a network to connect Docker containers and facilitate data sharing between them.

docker network create adobe

Step Eleven: Run the Author Docker Image

It’s time to run our Author Docker Image. First, create a local directory for the logs volume specified in the Dockerfile. Within the author subdirectory, create a directory named “logs.” Run the following command within the new logs folder:

Windows

docker run -d --name author -p 4502:4502 -p 5005:5005 --network adobe -v ${PWD}:/opt/aem/crx-quickstart/logs aem-author

macOS/Linux

docker run -d --name author -p 4502:4502 -p 5005:5005 --network adobe -v `pwd`:/opt/aem/crx-quickstart/logs aem-author

The command will return the ID of the new Docker container. It may take some time for the new AEM instance to start. To check its status, you can monitor the “error.log” file in the logs directory to check its status.

Windows

Get-Content -Path .\error.log -Wait

macOS/Linux

tail -f error.log

After AEM has finished starting up, check that everything is loading correctly by visiting: http://localhost:4502/aem/start.html.

Let’s stop the AEM container for the time being:

docker stop author

Step Twelve: Run the Publisher Docker Image

It’s time to run our Publisher Docker Image.  First, create a local directory for the logs volume specified in the Dockerfile. Within the publish subdirectory, create a directory named “logs.”  Run the following command within the new logs folder:

Windows

docker run -d --name publish -p 4503:4503 -p 5006:5006 --network adobe -v ${PWD}:/opt/aem/crx-quickstart/logs aem-publish

macOS/Linux

docker run -d --name publish -p 4503:4503 -p 5006:5006 --network adobe -v `pwd`:/opt/aem/crx-quickstart/logs aem-publish

The command will return the ID of the new Docker container. It may take some time for the new AEM instance to start. To check its status, you can monitor the “error.log” file in the logs directory to check its status.

Windows

Get-Content -Path .\error.log -Wait

macOS/Linux

tail -f error.log

After AEM has finished starting up, check that everything is loading correctly by visiting: http://localhost:4503/content.html.  You will see a “Not Found” page.  That is fine for now.

Let’s stop the AEM container for the time being:

docker stop publish

Step Thirteen: Start the Containers via Rancher Desktop

Open Rancher Desktop and go to the Containers tab in the left navigation pane. To start individual containers, check the box in the State column for each container you want to start, then click the Start button. To start all containers at once, check the box in the header row of the State column, and then click the Start button. Let’s go ahead and start all containers.

If you prefer using the command line, you can run:

docker start author
docker start publish

Containers Via Rancher Desktop

Step Fourteen: Create an AEM Project and install it on the Author and Publish instance

Since Docker’s mascot is a whale, I thought it would be fun to name our new AEM project after a famous fictional whale: Monstro from Pinocchio.

Run the following command from a command line (Note: you may have to run this command with elevated privileges):

mvn -B archetype:generate -D archetypeGroupId=com.adobe.aem -D archetypeArtifactId=aem-project-archetype -D archetypeVersion=50 -D aemVersion=cloud -D appTitle="Monstro" -D appId="monstro" -D groupId="com.monstro" -D frontendModule=general -D includeExamples=n

Once this project has been created, let us build and deploy it to our Author instance.

Run the following command from within the “Monstro” project:

mvn clean install -PautoInstallSinglePackage

Check that the project is installed by visiting the following URL to view the results: http://localhost:4502/editor.html/content/monstro/us/en.html.  You should see the following:

Project Monstro

Now, let us build and deploy the project to our Publish instance.

Run the following command from within the “Monstro” project:

mvn clean install -PautoInstallSinglePackagePublish

Verify that the project is installed by visiting this URL: http://localhost:4503/content/monstro/us/en.html.  Installation may take up to five minutes. After this period, you should see the following:

Post Installation Project Monstro

Step Fifteen: Set up the Publish Agent on Author

It’s time to configure the publish agent on our author instance. Go to this URL: http://localhost:4502/etc/replication/agents.author/publish.html.

Click the “Edit” button (next to settings).

Publish Agent On Author Setup

  • Click the checkbox next to “Enabled”
  • Enter “admin” in the “Agent User Id” field
  • Navigate to the Transport tab and enter the following in the URI field:  http://publish:4503/bin/receive?sling:authRequestLogin=1
  • Instead of using “localhost,” the hostname for our publish instance is our container’s name, “publish”
  • In the “username” field, enter “admin,” and in the “password” field, enter the admin’s password
  • Click the “OK” button to save the Agent settings
  • Click the “Test Connection” link, and the replication test should be successful

Step Sixteen: Publish content from the Author

Go back to http://localhost:4502/editor.html/content/monstro/us/en.html. Edit the “Hello, World” component by changing the text from “lalala :)” to “Monstro is the enormous, fearsome whale from Disney’s 1940 animated film Pinocchio.” Verify the update and publish the page. Then, check http://localhost:4503/content/monstro/us/en.html to see your changes on the Publisher as well.

Step Seventeen: Create the Dispatcher Container

Make sure the publisher instance is running before proceeding. Extract the AEM SDK Dispatcher tools.

Windows

Expand-Archive .\aem-sdk-dispatcher-tools-2.0.222-windows.zip
Rename-Item -Path .\aem-sdk-dispatcher-tools-2.0.222-windows -NewName dispatcher-sdk-2.0.222

macOS/Linux

chmod +x ./aem-sdk-dispatcher-tools-2.0.222-unix.sh
./aem-sdk-dispatcher-tools-2.0.222-unix.sh

Since we’ve set up a custom network for our AEM containers, the docker run script won’t function correctly because it doesn’t recognize this network. Let’s modify the docker run script.

Windows

Open “dispatcher-sdk-2.0.222\bin\docker_run.cmd” in your favorite editor.

Add the “–network adobe” argument to the docker command inside the “else” statement.

Modify Docker Run Script For Windows

macOS/Linux

Open “dispatcher-sdk-2.0.222/bin/docker_run.sh” in your favorite editor.

Add the “–network adobe” argument to the docker command inside the “else” statement.

Modify Docker Run Script For macOS/Linux

Execute the docker run script with the following parameters. Be sure to replace the dispatcher source path with the path to your “monstro” source.

Windows

.\ dispatcher-sdk-2.0.222\bin\docker_run.cmd C:\Users\shann\Sites\monstro\dispatcher\src publish:4503 8080

macOS/Linux

./dispatcher-sdk-2.0.222/bin/docker_run.sh ~/Sites/monstro/dispatcher/src publish:4503 8080

Once the text stream in your terminal has stopped, go to http://localhost:8080/.  You should see the following:

Dispatch Container For Project Monstro

Open Rancher Desktop and navigate to the Containers tab. Locate the container with an unusual name. If you stop this container, it won’t be possible to start it again. Please go ahead and stop this container. The dispatcher code running in your terminal will also terminate. We want this container to be more permanent, so let’s make some additional changes to the docker run script.

Creating A Permanent Container For Project Monstro

Windows

Open “dispatcher-sdk-2.0.222\bin\docker_run.cmd” in your favorite editor.

macOS/Linux

Open “dispatcher-sdk-2.0.222/bin/docker_run.sh” in your favorite editor.

Add the “–name dispatcher” argument to the “docker” command within the “else” statement. Also, remove the “–rm” switch. According to Docker documentation, the “–rm” switch automatically removes the container and its associated anonymous volumes when it exits, which is not what we want.

Windows

Modify Docker Run Script For Windows 2

macOS/Linux

Modify Docker Run Script For Macos Linux 2

Run the docker run command in your terminal again:

Windows

.\ dispatcher-sdk-2.0.222\bin\docker_run.cmd C:\Users\shann\Sites\monstro\dispatcher\src publish:4503 8080

macOS/Linux

./dispatcher-sdk-2.0.222/bin/docker_run.sh ~/Sites/monstro/dispatcher/src publish:4503 8080

Open Rancher Desktop and go to the Containers tab. You should see a container named “dispatcher.” Stop this container. The dispatcher code running in your terminal will terminate, but the container will remain in Rancher Desktop. You can now stop and restart this container as many times as you’d like. You can also start and stop the dispatcher via the command line:

docker start dispatcher
docker stop dispatcher

Docker Provides Value and Flexibility

We have an author and publisher AEM instance running inside a Docker container. Additionally, we have a dispatcher container created using the source from the Monstro project. Although this dispatcher container isn’t very useful, the advantage of Docker is that you can easily delete and create new containers as needed.

I hope you found this blog helpful. I’ve been using Docker on my local machine for the past eight years and value the flexibility it provides. I can’t imagine going back to managing a local AEM instance or dealing with Apache configurations to get the dispatcher working. Those days are behind me.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Shannon Sumner, Senior Technical Consultant

More from this Author

Follow Us