April 1, 2020
Estimated Post Reading Time ~

How to set up Shareable Docker Image for Adobe CQ/AEM

Use case
Large Setup time for developers
Inconsistent environments across all boxes
Flexible in container testing
No Single repository for whole system artifacts

What is Docker Docker is a platform for developers and sysadmins to develop, ship, and run applications. Docker lets you quickly assemble applications from components and eliminates the friction that can come when shipping code. Docker lets you get your code tested and deployed into production as fast as possible.
More information about Docker can be found here https://docs.docker.com/
Check Docker Cheatsheet: https://github.com/wsargent/docker-cheat-sheet

Set up docker requires two-part to work,

Docker Hub or Docker registry (Where images are stored). You don't have to set up this part. We already have a private docker registry set up for you.
Docker client (To work with docker images). You need to install this in your local. Please check https://docs.docker.com/installation/ and based on your OS you need to install one. I have instructions to install it on Redhat Linux.

What would you get after following below instruction?

A Private Docker Hub, where you can manage AEM docker package.
A docker image that will have author, publish and dispatcher instance.
Steps to manage your docker hub and local image and make changes to them.
Assumption: I have a docker registry set up for Red hat Linux. You might need different steps for different OS. I assume that on your OS mount you have a mount for /export. If this mount is not there then change paths in the script.

Docker is only supported FOR RED HAT LINUX VERSION > 6.5
(Use command cat /etc/*release to find your Linux version)

Set Up Private Docker Registry
Prerequisite:
If you are using redhat then

Reference:
https://github.com/docker/docker-registry

https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-14-04

#Install Docker Client
yum -y remove docker
yum install docker-io
yum -y update docker-io
#This will start docker deamon
service docker start

#Install docker registry
yum install python-devel libevent-devel python-pip gcc xz-devel
python-pip install docker-registry[bugsnag,newrelic,cors]
mkdir -p /export/apps/docker/
cd /export/apps/docker/
git clone https://github.com/dotcloud/docker-registry.git
cd docker-registry
cp config/config_sample.yml config/config.yml
vi config/config.yml


#Change the local path and index path as given in https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-14-04

mkdir -p /export/apps/docker/registry
chmod 777 /export/apps/docker/registry
/etc/init.d/iptables stop
cp config/config.yml /usr/lib/python2.6/site-packages/docker_registry/lib/../../config
mkdir -p /export/apps/docker-registry/logs
gunicorn --access-logfile /export/apps/docker-registry/logs/access.log --error-logfile /export/apps/docker-registry/logs/server.log -k gevent --max-requests 100 --graceful-timeout 3600 -t 3600 -b 0.0.0.0:5000 -w 8 docker_registry.wsgi:application &
#Now install nginx for proxy and https access
yum install nginx apache2-utils
vi /etc/yum.conf

#Copy data as given in https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-14-04

yum install nginx apache2-utils
yum install httpd-tools
#Create a user for secure access
htpasswd -c /etc/nginx/docker-registry.htpasswd admin
htpasswd /etc/nginx/docker-registry.htpasswd test
vi /etc/nginx/conf.d/docker-registry
#This is to avoid nginx error while start
mkdir /var/cache/nginx
mkdir /var/cache/nginx/client_temp
service nginx restart
#Protect Nginx
#All steps here https://www.digitalocean.com/community/tutorials/how-to-set-up-a-private-docker-registry-on-ubuntu-14-04

Set Up docker Image using docker file
Once the docker is installed to create a dummy directory and put your jar file, license file, Hotfix and other files into it. More information about Docker file https://docs.docker.com/reference/builder/

Assumption:
1) You have AEM jar file
2) You have License File
3) You have your version of JDK
4) You have compiled HTTPD
5) They all are in the same folder where Dockerfile is

For this create a file called Dockerfile and copy below. MAKE CHANGES BASED ON YOUR REQUIREMENT

FROM centos
#Install and set java home
RUN mkdir -p /export/apps/jdk
ADD JDK-1_7_0_51 /export/apps/jdk/JDK-1_7_0_51
ENV JAVA_HOME /export/apps/jdk/JDK-1_7_0_51
ENV PATH $PATH:$JAVA_HOME/bin
#Install CQ Author
RUN mkdir -p /export/apps/aem/author
WORKDIR /export/apps/aem/author
ADD cq5-publish-p4503.jar /export/apps/aem/author/cq5-author-p4502.jar
ADD license.properties /export/apps/aem/author/license.properties
RUN java -jar cq5-author-p4502.jar -unpack -v
ADD quickstart_author /export/apps/aem/author/crx-quickstart/bin/quickstart
RUN mkdir -p /export/apps/aem/author/crx-quickstart/install
ADD hotfix/* /export/apps/aem/author/crx-quickstart/install/

#Now start Publish Instance
RUN mkdir -p /export/apps/aem/publish
WORKDIR /export/apps/aem/publish
ADD cq5-publish-p4503.jar /export/apps/aem/publish/cq5-publish-p4503.jar
ADD license.properties /export/apps/aem/publish/license.properties
RUN java -jar cq5-publish-p4503.jar -unpack -v
ADD quickstart_publish /export/apps/aem/publish/crx-quickstart/bin/quickstart
RUN mkdir -p /export/apps/aem/publish/crx-quickstart/install
#Add your hotfixes here
ADD hotfix/* /export/apps/aem/publish/crx-quickstart/install/
#Set up all CQ ENV
ENV CQ_FOREGROUND y
ENV CQ_VERBOSE y
ENV CQ_NOBROWSER y
ENV CQ_JVM_OPTS "-server -Xmx1524M -Xms512M -XX:MaxPermSize=512M"

#Now install Dispatcher
ADD httpd /export/apps/httpd
RUN chmod -R 777 /export/apps/httpd/bin
RUN ln -sf /export/apps/httpd/modules/dispatcher-apache2.2-4.1.2.so /export/apps/httpd/modules/mod_dispatcher.so
ADD www /export/www
RUN chown -R daemon:daemon /export/www
WORKDIR /export/apps
#Add supervisor to run multiple deamon

RUN yum install -y epel-release && \
yum install -y supervisor && \
yum clean all
EXPOSE 80 443 4502 4503
# supervisor is needed to run multiple process in same docker image
RUN echo "[supervisord]" > /etc/supervisord.conf && \
echo "nodaemon=true" >> /etc/supervisord.conf && \
echo "" >> /etc/supervisord.conf && \
echo "[program:aem_author]" >> /etc/supervisord.conf && \
echo "command=/export/apps/aem/author/crx-quickstart/bin/quickstart" >> /etc/supervisord.conf && \
echo "" >> /etc/supervisord.conf && \
echo "[program:aem_publish]" >> /etc/supervisord.conf && \
echo "command=/export/apps/aem/publish/crx-quickstart/bin/quickstart" >> /etc/supervisord.conf && \
echo "" >> /etc/supervisord.conf && \
echo "[program:httpd]" >> /etc/supervisord.conf && \
echo "command=/export/apps/httpd/bin/apachectl -D FOREGROUND" >> /etc/supervisord.conf
CMD ["/usr/bin/supervisord"]

Once the Docker file is there build and create your private docker image using the following command. This will create a shareable docker image

#Make sure that you run this command from the same directory where docker file is
#Also makes sure that all files are at the same location
docker build --tag="localhost:5000/wemblog/microsites_aem:5.6" .
#Make sure that image exists before a push
docker images
#Push image to a registry
docker push localhost:5000/wemblog/microsites_aem:5.6

Once Docker registry is installed and you have a shareable image, now you can install docker client on any other machine

Set up Docker Client
Prerequisite: Based on your OS please install docker client using https://docs.docker.com/installation/

Change the default path if there is not enough space

Docker by default gets installed under /var/lib/docker in Red Hat. Make sure that you have enough space there. If not then you have to do the following.

#Check if /var is getting filled
df -k
#If /var space is not more than 50GB do following
sudo su
#Stop Docker
service docker stop
#Copy all files to folder that have enough space
#usually in linux boxes there is enough space under /export
#Create a dummy directory 'mkdir /export/apps/docker'
cp -R /var/lib/docker/ <Your other folder>
#Create backup
mv /var/lib/docker/ /var/lib/docker.backup
#Create softlink so in above example it would be 'ln -s /export/apps/docker/ /var/lib/docker'
ln -s <Your other folder> /var/lib/docker
#Start docker
service docker start
#Run following command to check change (look for Data file and Metadata File value)
docker info
#If everything is fine then
rm -rf /var/lib/docker.backup

Set Up docker for Non-SSL version

By default, Docker uses SSL to communicate to the docker registry. If you do not have a valid cert installed then you might need to do the following

#This is to avoid the following error
# FATA[0000] Error: Invalid registry endpoint certificate signed by unknown authority. If this private registry supports only HTTP or HTTPS # with an unknown CA certificate, please add `--insecure-registry HOST` to the daemon's arguments. In the case of HTTPS, if you have access # to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/HOST/ca.crt

# For red hat Linux
vi /etc/sysconfig/docker
# Add following line
other_args="--insecure-registry <Your-Registry-HOST>"
service docker restart

# For Mac book

boot2docker init
boot2docker up
boot2docker ssh "echo $'EXTRA_ARGS=\"--insecure-registry <Your registry host>\"' | sudo tee -a /var/lib/boot2docker/profile && sudo /etc/init.d/docker restart"

Set up local docker instance using docker client
Do following to start your local AEM instance using docker registry and docker client

#First make sure that you can connect to docker registry
curl -u admin: admin https://<your docker registry host>
#If this works make sure that you can ping images in the registry
curl -u admin:admin https://<your docker registry host>/v1/_ping
#If this works login into docker registry server (admin: admin)
docker login https://<your docker registry host>
#if this works then download docker images
docker pull <your docker registry host>/wemblog/aem_microsite:5.6
# After the download is done start your docker image using the following command
# You can also a docker image using 'docker run -d -t -i -p 4502:4502 <Image ID>'
# To get image ID you can use command 'docker images'
docker run -d -t -i -p 4502:4502 -p 4503:4503 -p 8080:80 -p 8443:443 <your docker registry host>/wemblog/aem_microsite:5.6
# This command will start the author on 4502, publish on 4503 and apache on 8080 and 8443. If port 80 and 443 of your local is not busy then start apache on 80 and 443 by changing the port
# THIS MIGHT TAKE SOME TIME (Some case 15 Minute) to start
# This will start a docker image in the background (-d) on port 4502 and expose port 4502
# Server might take some time to start
# Make sure that Docker is running using the command
docker ps
# You should see something like this for your image
#CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
#e1d870f39bda wemblog/aem_microsite:5.6 "/usr/bin/supervisor 7 minutes ago Up 7 minutes 0.0.0.0:4502->4502/tcp, #0.0.0.0:4503->4503/tcp, 0.0.0.0:8090-#>80/tcp, 0.0.0.0:8443->443/tcp <some name>
# Now you can access your author using http://locahost:4502, publish using http://locahost:4503, apache using http://locahost:8090 &https://locahost:8443
# If you can not access this on Mac then run "boot2docker IP" and then use output IP and then port to access.
# In your mac you can also run $ echo "$(boot2docker IP) localhost" | sudo tee -a /etc/hosts
# To check log use following command
docker logs -f <Container ID>
# Once you see http://localhost:4503/ Quickstart started
# This means that CQ is started in a container
# If this does not return anything that means your docker instance did not come up
# With docker ID from the above command run following
docker exec -it <Docker id> bash
# This will take you to VM environment and from there you can go /export/apps/aem/<author or publish or httpd> to check the log for either author or publish or apache
# You can also change your configuration there and start and stop your instances
# Note that after making some changes if you start your instance using initial docker run command, your changes might be overridden.
# If you want to keep your changes. Commit your changes after the change. For more info look into docker commit command
# to exit from container just type exit. this will not stop the container. You can also check it with docker ps

#You can also run following to check the status of your container. If it is using the right location
docker inspect <Container ID>
# To stop your docker container you can use
# IMPORTANT: Please commit your docker image before you do any change. When you stop and start your docker image new VM will be started
docker commit --message="<What did you do>" <Container ID> <your docker registry host>/wemblog/aem_microsite:5.6
docker stop <Container ID>

How to update docker image please follow below step to update your docker image
# First check if docker process is running
docker ps
# Make sure to commit your changes before you stop
docker commit --message="<What did you do>" <Container ID> <your docker registry>/wemblog/aem_microsite:5.6
# Grab container ID from the above command
docker stop <Container ID>
# Then pull the new image
docker pull <your docker registry>/<new or existing docker tag name>
# Once docker new docker image is available to start your image
docker run -d -t -i -p 4502:4502 -p 4503:4503 -p 8080:80 -p 8443:443 <your docker registry>/<new or existing docker tag name>
# Above command could be different depending upon what is present in the docker image. The email should have that information
# make sure that docker image is up
docker ps
# Go to your system
# If this is a brand new image, You might have to upload content and code again.

Troubleshoot
Symptom: You are not able to access your instance from an external machine
Solution: Try to restart your machine using 'reboot' for Linux box and restart in mac
Symptom: Docker is not starting on mac
Solution: Make sure that you have localhost entry in /etc/hosts file. e.g. 127.0.0.1 localhost. then do the following

boot2docker delete
boot2docker download
boot2docker init
boot2docker up
# End of this you will be asked to add some env variable in your ~/.bash_profile
# Open bash profile and add them

Symptom: Getting the following error in mac

FATA[0032] An error occurred trying to connect: Get https://192.168.59.103:2376/v1.17/containers/json: dial tcp 192.168.59.103:2376: i/o timeout
Solution: http://cxwangyi.github.io/notes/2015-01-13-docker-pitfalls.html

boot2docker stop
boot2docker destroy
boot2docker init
boot2docker up
docker version

Symptom: On Mac local box not able to access the instance using localhost:<port number> (https://docs.docker.com/installation/mac/)
Solution:
# Run following command
echo "$(boot2docker IP) localhost" | sudo tee -a /etc/hosts
# Then access your instance using localhost
# If you want to create other vhost then change the above command with your vhost. For example
echo "$(boot2docker IP) localhost.wemblog.com" | sudo tee -a /etc/hosts

Some use the full docker command

######## start docker in debug mode ##########
docker -dD

####### Remove Docker Image ############
# Get Docker image
docker images
# Remove image
docker rmi <Image ID>
#If process is already using this image then run this command and then remove image
docker rm $(docker ps -aq)
#Remove image

######## Change Temp Directory Location ##############
vi /etc/sysconfig/docker
# Add following data
DOCKER_TMPDIR=/export/apps/docker
DOCKER_OPTS="-g /export/apps/docker”

############ Set Up proxy ###################
vi /etc/sysconfig/docker
#To add proxy
export HTTP_PROXY="<proxy host>:<proxy port>"
export HTTPS_PROXY="<proxy host>:<proxy port>"

Upload content
You can use the Recap tool http://adamcin.net/net.adamcin.recap/ to install content once the image is set up. You can even put this recap tool as part of your image when you are creating a docker image. Just put them under the install folder.

Note that every time you update your image, Uploaded content or local changes might get overridden. You have to commit your changes using docker commit and then apply the update on top of that and then share your image.

Useful resource: http://www.techinsight.io/review/adobe-experience-manager/incontainer-testing-for-aem-with-docker/


By aem4beginner

1 comment:

  1. That Dockerfile example is based off of
    https://gist.github.com/yupadhyay/8019f9fcb4305d96ee81

    ReplyDelete

If you have any doubts or questions, please let us know.