Skip navigation
All Places > Alfresco Content Services (ECM) > Blog > 2018 > November
2018

Introduction

The way you deploy and run the Alfresco Content Services (ACS) solution has changed significantly in version 6.0. Traditionally you would download an installer that would install Java, Tomcat, Database, WARs, tools, etc, and things would be configured to work together. Then you would use a script to kick things off. That’s no longer the case and there are no installers available. We will be working with Docker containers instead.

 

It’s now possible to kick off an ACS 6.0 solution from a number of Docker images. These images are available in the https://hub.docker.com repository. However, kicking off individual Docker containers based on these images, and configuring them to work together, might not be the most productive way to get up and running with ACS. To make things easier, and achieve a one-click to deploy and run solution, a Docker compose file is available to quickly deploy and run the ACS solution when you need to test something or work on a proof-of-concept (PoC).

 

There are also Helm Charts available to deploy the ACS solution in production as a Kubernetes cluster in for example AWS, this is not covered in this article.

Source Code and Tools

The source code for this article can be downloaded here. It will become useful when you read the section about creating custom ACS images.

 

There is now an Alfresco Extension Project generator that implements a lot of the concepts discussed in this article around building extensions and deploying them to containers. 

Concepts and Technologies

The following is a list of concepts (terms) and technologies that you will come in contact with when deploying and using the Alfresco Content Services version 6.0. If you know all about Docker, then you can skip this part.

Virtual Machine Monitor (Hypervisor)

A Hypervisor is used to run other OS instances on your local host machine. Typically it's used to run a different OS on your machine, such as Windows on a Mac. When you run another OS on your host it is called a guest OS, and it runs in a so called Virtual Machine (VM).

Image

An image is a number of layers that can be used to instantiate a container. This could be, for example, Java + Apache Tomcat. You can find all kinds of Docker Images on the public repository called Docker Hub. There are also private image repositories (for things like commercial enterprise images), such as the one Alfresco uses called Quay.  

Container

An instance of an image is called a container. You have an image, which is a set of layers as described. If you start this image, you have a running container of this image. You can have many running containers of the same image.

Docker

Docker is one of the most popular container platforms. Docker provides functionality for deploying and running applications in containers based on images.

Docker Compose

When you have many containers making up your solution, such as with ACS, and you need to configure each one of the containers so they work nicely together, then you need a tool for this.

Docker Compose is such a tool for defining and running multi-container Docker applications locally. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

Dockerfile

A Dockerfile is a script containing a successive series of instructions, directions, and commands which are to be executed to form a new Docker image. Each command executed translates to a new layer in the image, forming the end product. They replace the process of doing everything manually and repeatedly. When a Dockerfile is finished executing, you end up having built a new image, which then you use to start a new Docker container.

Difference between Containers and Virtual Machines

It is important to understand the difference between using containers and using VMs. Here is a picture from What is a Container | Docker  that illustrates:

 

 

The main difference is that when you are running a container you are not kicking off a complete new OS instance. And this makes containers much more lightweight and quicker to start. A container is also taking up much less space on your hard-disk as it does not have to ship the whole OS.

Installing Software Required to Deploy ACS

Before we can deploy and run the Alfresco Content Services it is necessary to install the technologies that it uses.

Docker

You probably already have Docker installed as everything these days is easily accessible and run as containers. If you don't, go to the Docker Store and download the latest stable community edition (CE). Make sure the Docker daemon is running:

 

mbergljung$ docker -v

Docker version 17.09.0-ce, build afdb6d4

 

Also, verify that you have the recommended Docker version for running ACS, which is at least 17.09. You also want to verify the Docker Compose version, which should be at least 1.16.1:

$ docker-compose -v

docker-compose version 1.18.0, build 8dd22a9

 

If you are on Windows make sure that you are executing Docker commands from Windows PowerShell:

 

Getting to know the public Alfresco Docker Images

To find out about all the Alfresco images that are available at the Docker Hub registry go to https://hub.docker.com/u/alfresco/ and you will see a list of images belonging to the alfresco user. You should see something similar to the following screenshot (note: not all images are visible in the screenshot):

 

 

As we can see, a number of Docker images are available that relate to ACS:

 

  • alfresco/alfresco-share - the Alfresco Share web interface (i.e. share.war) running on Apache Tomcat
  • alfresco/alfresco-search-services - the Solr 6 based search service running on Jetty
  • alfresco/alfresco-content-repository-community - the Alfresco Repository app (i.e. alfresco.war) running on Apache Tomcat

 

There are also other supporting features available, such as Docker images for image and document transformation:

 

  • alfresco/alfresco-docker-imagemagick
  • alfresco/alfresco-docker-libreoffice
  • alfresco/alfresco-docker-alfresco-pdf-renderer

To build the alfresco/alfresco-content-repository-community image Alfresco uses the GitHub - Alfresco/acs-community-packaging  project. This project does not include any deployment templates. The GitHub - Alfresco/acs-community-deployment project contains deployment templates and instructions. It includes a Docker Compose script that can be used to launch a demo, test, or PoC ACS 6.0 system. You can customize this script if you like in order to run with different versions than those set by default, which are usually the latest versions.

When the ACS system is up and running you will have the following containers running:

  • Alfresco Community Repository 6.0 with:
    • Alfresco Share Services AMP
    • Alfresco Office Services (AOS) AMP
    • Alfresco vti-bin war - that helps with AOS integration
    • Alfresco Google Docs Integration Repo AMP
  • Alfresco Share 6.0 with:
    • Alfresco Google Docs Integration Share AMP
  • Alfresco Search Services (Solr 6)
  • A Postgres Database

 

To build custom images based on these Alfresco images in Docker Hub you need to create some Docker files. While doing this you can include custom AMPs and JARs. We will see how to do that later in the article. Before we do that we will walk through how to start an ACS system with Docker Compose and how to start an ACS system container by container.

Introduction to the Alfresco ACS Community Packaging Project

As mentioned, this is the project that is used to build Alfresco Community Repository artifacts, such as the Docker Image for ACS 6.0 Repo. Clone the ACS Community Packaging project so we can have a look at it:

 

$ git clone https://github.com/Alfresco/acs-community-packaging.git

 

$ cd acs-community-packaging/

 

Now, let’s look at what the different directories contain:

 

$ tree

.

├── CONTRIBUTING.md

├── LICENSE

├── README.md

 

(Contains a build script to create a Distribution ZIP with Repo, Share, and Solr4 etc, so you can install manually or facilitate upgrades)

├── distribution

│   ├── pom.xml

│   └── src

│       ├── assembly

│       │ └── distribution.xml

│       └── main

│           └── resources

│               ├── README.txt

│               ├── bin

│               │ ├── apply_amps.bat

│               │ ├── apply_amps.sh

│               │ ├── clean_tomcat.bat

│               │ └── clean_tomcat.sh

│               ├── licenses

│               │ ├── 3rd-party

...

│               │ ├── license.txt

│               │ └── notice.txt

│               └── web-server

│                   ├── conf-Tomcat7

│                   │   └── Catalina

│                   │       └── localhost

│                   │           └── alfresco.xml

│                   └── conf-Tomcat8

│                       └── Catalina

│                           └── localhost

│                               └── alfresco.xml

 

(Contains the Dockerfile to build the Alfresco Repo Docker image - alfresco/alfresco-content-repository-community)

├── docker-alfresco

│   ├── Dockerfile

│   ├── pom.xml

│   └── test

│       ├── docker-compose.yml

│       └── test.env

  

(Builds the alfresco.war)

├── war

 

As we can see, there’s no Alfresco Share or Search Service docker files. They reside in their own projects:

 

 

Note: We don’t need these projects for this article but it good to know about them to get an idea of how the images are produced.

 

If you are interested in the ACS 6.0 Enterprise packaging, then have a look at the http://github.com/Alfresco/acs-packaging project.

Introduction to the Alfresco ACS Community Deployment Project

This project contains the Docker Compose file that we will use in this article to start up an ASC Community 6.0 environment locally. If you are interested in the Kubernetes Helm charts to be able to deploy ACS Community with Kubernetes, then this is included in this project as well (Note: Kubernetes deployment is not covered in this article).

 

Clone the ACS Community Deployment project so we can have a look at it:

 

$ git clone https://github.com/Alfresco/acs-community-deployment.git 

 

$ cd acs-community-deployment/

 

Now, let’s look at what the different directories contain:

 

acs-community-deployment mbergljung$ tree

.

├── CONTRIBUTING.md

├── LICENSE

├── README.md

 

(Contains the Docker Compose YAML file to be able to start a full ACS 6.0 environment with Repo, Share, Solr, PostgreSQL)

├── docker-compose

│   ├── docker-compose.yml

│   └── test.env

 

(Contains Helm Charts to be able to deploy ACS Kubernetes cluster to AWS or locally via Minikube) 

└── helm

    └── alfresco-content-services-community

        ├── Chart.yaml

        ├── requirements.yaml

        ├── templates

        │   ├── NOTES.txt

        │   ├── _helpers.tpl

        │   ├── config-repository.yaml

        │   ├── config-share.yaml

        │   ├── deployment-repository.yaml

        │   ├── deployment-share.yaml

        │   ├── ingress-repository.yaml

        │   ├── ingress-share.yaml

        │   ├── svc-repository.yaml

        │   ├── svc-share.yaml

        └── values.yaml

 

If you are interested in the ACS 6.0 Enterprise deployment, then have a look at the http://github.com/Alfresco/acs-deployment project.

 

Deploying the ACS system with Docker Compose

Let’s see how easy it is to kick off a demo, test, or PoC ACS 6.0 solution with the supplied Docker Compose file. It will be similar to using the old installer and the shell script, except it will now be a whole lot easier to remove the installation and to keep several installations in parallel.

Using the Docker Compose file to start the ACS solution

After you have cloned the ACS Community Packaging project it’s time to get started.

Make sure the local machine has ports 5432, 8080, 8082, and 8083 free as they are used in the docker-compose.yml file.

Step into the directory where you cloned the acs-community-deployment project, then navigate into the docker-compose sub-directory, followed by command docker-compose up (if on Windows use Windows PowerShell):

 

acs-community-deployment mbergljung$ cd docker-compose/

docker-compose mbergljung$docker-compose up

 

Creating network "dockercompose_default" with the default driver

Pulling solr6 (alfresco/alfresco-search-services:1.1.1)...

1.1.1: Pulling from alfresco/alfresco-search-services

6fd64836e300: Already exists

8ff6188dadfc: Already exists

d1b16fb40528: Already exists

fed33e3ce39c: Already exists

96f24514a7b3: Pull complete

6f415ea07e70: Pull complete

e2f858f39b3d: Pull complete

Digest: sha256:be7bf1463c55ced0058becdcd9ad952b3f770213e55b82c119d0eca95e70c7d8

Status: Downloaded newer image for alfresco/alfresco-search-services:1.1.1

Pulling alfresco (alfresco/alfresco-content-repository-community:6.0.5-ea)...

6.0.5-ea: Pulling from alfresco/alfresco-content-repository-community

18b8eb7e7f01: Already exists

f9d093c4cd43: Pull complete

05b40fb97183: Pull complete

6afa3ee9ddb6: Pull complete

 

...

Digest: sha256:9ab9496c2e3f6f26877f27db1c003b64d7b3ffe0aefc0ffd123dbfa6cddd8f5a

Status: Downloaded newer image for alfresco/alfresco-content-repository-community:6.0.5-ea

Creating dockercompose_solr6_1    ... done

Creating dockercompose_share_1    ... done

Creating dockercompose_alfresco_1 ... done

Creating dockercompose_postgres_1 ... done

Attaching to dockercompose_share_1, dockercompose_alfresco_1, dockercompose_solr6_1, dockercompose_postgres_1

share_1     | Replace 'REPO_HOST' with 'alfresco' and 'REPO_PORT' with '8080'

share_1     | 23-May-2018 07:15:34.483 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:        Apache Tomcat/8.5.23

 

...

share_1     | 23-May-2018 07:15:34.850 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]

share_1     | 23-May-2018 07:15:34.897 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read

share_1     | 23-May-2018 07:15:34.905 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["ajp-nio-8009"]

share_1     | 23-May-2018 07:15:34.911 INFO [main] org.apache.tomcat.util.net.NioSelectorPool.getSharedSelector Using a shared selector for servlet write/read

share_1     | 23-May-2018 07:15:34.912 INFO [main] org.apache.catalina.startup.Catalina.load Initialization processed in 1286 ms

share_1     | 23-May-2018 07:15:34.976 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]

share_1     | 23-May-2018 07:15:34.977 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.23

share_1     | 23-May-2018 07:15:34.998 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/manager]

postgres_1  | The files belonging to this database system will be owned by user "postgres".

postgres_1  | This user must also own the server process.

postgres_1  |

postgres_1  | The database cluster will be initialized with locale "en_US.utf8".

postgres_1  | The default database encoding has accordingly been set to "UTF8".

postgres_1  | The default text search configuration will be set to "english".

postgres_1  |

postgres_1  | Data page checksums are disabled.

postgres_1  |

postgres_1  | fixing permissions on existing directory /var/lib/postgresql/data ... ok

postgres_1  | creating subdirectories ... ok

postgres_1  | selecting default max_connections ... 100

postgres_1  | selecting default shared_buffers ... 128MB

postgres_1  | selecting dynamic shared memory implementation ... posix

postgres_1  | creating configuration files ... ok

postgres_1  | running bootstrap script ... ok

share_1     | 23-May-2018 07:15:36.158 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/manager] has finished in [1,157] ms

share_1     | 23-May-2018 07:15:36.160 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/docs]

share_1     | 23-May-2018 07:15:36.186 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/docs] has finished in [26] ms

share_1     | 23-May-2018 07:15:36.187 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/examples]

alfresco_1  | 23-May-2018 07:15:36.245 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:        Apache Tomcat/8.5.28

 

...

 

alfresco_1  | 23-May-2018 07:15:37.284 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]

share_1     | 23-May-2018 07:15:37.320 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/ROOT] has finished in [86] ms

share_1     | 23-May-2018 07:15:37.321 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/share]

 

...

alfresco_1  | 23-May-2018 07:15:37.490 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]

alfresco_1  | 23-May-2018 07:15:37.490 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet Engine: Apache Tomcat/8.5.28

alfresco_1  | 23-May-2018 07:15:37.586 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/usr/local/tomcat/webapps/ROOT.war]

alfresco_1  | 23-May-2018 07:15:37.693 WARNING [localhost-startStop-1] org.apache.catalina.startup.SetContextPropertiesRule.begin [SetContextPropertiesRule]{Context} Setting property 'debug' to '100' did not find a matching property.

...

postgres_1  | waiting for server to start....2018-05-23 07:15:37.855 UTC [39] LOG:  listening on IPv4 address "127.0.0.1", port 5432

...

org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory [/usr/local/tomcat/webapps/alfresco]

solr6_1     | 2018-05-23 07:15:44.592 INFO  (main) [   ] o.e.j.s.Server jetty-9.3.8.v20160314

solr6_1     | 2018-05-23 07:15:45.800 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter  ___      _       Welcome to Apache Solr? version 6.3.0

solr6_1     | 2018-05-23 07:15:45.812 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter / __| ___| |_ _   Starting in standalone mode on port 8983

solr6_1     | 2018-05-23 07:15:45.813 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter \__ \/ _ \ | '_|  Install dir: /opt/alfresco-search-services/solr

solr6_1     | 2018-05-23 07:15:46.072 INFO  (main) [   ] o.a.s.s.SolrDispatchFilter |___/\___/_|_|    Start time: 2018-05-23T07:15:45.817Z

solr6_1     | 2018-05-23 07:15:48.368 INFO  (main) [   ] o.e.j.s.ServerConnector Started ServerConnector@71687585{HTTP/1.1,[http/1.1]}{0.0.0.0:8983}

solr6_1     | 2018-05-23 07:15:48.382 INFO  (main) [   ] o.e.j.s.Server Started @5374ms

share_1     | 23-May-2018 07:15:49.439 INFO [localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

share_1     | May 23, 2018 7:15:49 AM org.apache.catalina.core.ApplicationContext log

share_1     | INFO: No Spring WebApplicationInitializer types detected on classpath

share_1     | May 23, 2018 7:15:49 AM org.apache.catalina.core.ApplicationContext log

share_1     | INFO: Initializing Spring root WebApplicationContext

share_1     | 2018-05-23 07:15:56,036  INFO  [config.packaging.ModulePackageManager] [localhost-startStop-1] Found 1 module package(s)

share_1     |  2018-05-23 07:15:56,043  INFO  [config.packaging.ModulePackageManager] [localhost-startStop-1] Alfresco / Google Docs Share Module, 3.0.4.2, The Share side artifacts of the Alfresco / Google Docs Integration.

share_1     |

share_1     |  2018-05-23 07:15:56,735  INFO  [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor freemarker for extension ftl

share_1     |  2018-05-23 07:15:56,741  INFO  [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor javascript for extension js

share_1     |  2018-05-23 07:15:56,753  INFO  [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor freemarker for extension ftl

share_1     |  2018-05-23 07:15:56,755  INFO  [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor javascript for extension js

alfresco_1  | 23-May-2018 07:15:57.311 INFO [localhost-startStop-1] org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.

alfresco_1  | May 23, 2018 7:15:57 AM org.apache.catalina.core.ApplicationContext log

alfresco_1  | INFO: No Spring WebApplicationInitializer types detected on classpath

alfresco_1  | May 23, 2018 7:15:57 AM org.apache.catalina.core.ApplicationContext log

alfresco_1  | INFO: Initializing Spring root WebApplicationContext

share_1     |  2018-05-23 07:16:01,063  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 393 Web Scripts (+0 failed), 411 URLs

share_1     |  2018-05-23 07:16:01,063  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 8 Package Description Documents (+0 failed)

share_1     |  2018-05-23 07:16:01,064  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 0 Schema Description Documents (+0 failed)

share_1     |  2018-05-23 07:16:01,148  INFO  [extensions.webscripts.AbstractRuntimeContainer] [localhost-startStop-1] Initialised Surf Container Web Script Container (in 4380.056ms)

share_1     |  2018-05-23 07:16:01,178  INFO  [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor freemarker for extension ftl

share_1     |  2018-05-23 07:16:01,185  INFO  [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor javascript for extension js

share_1     |  May 23, 2018 7:16:02 AM org.apache.catalina.core.ApplicationContext log

share_1     | INFO: org.tuckey.web.filters.urlrewrite.UrlRewriteFilter INFO: loaded (conf ok)

share_1     | May 23, 2018 7:16:02 AM org.apache.catalina.core.ApplicationContext log

share_1     | INFO: Initializing Spring FrameworkServlet 'Spring Surf Dispatcher Servlet'

share_1     | 23-May-2018 07:16:02.147 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/share] has finished in [24,826] ms

share_1     | 23-May-2018 07:16:02.161 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]

share_1     | 23-May-2018 07:16:02.178 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]

share_1     | 23-May-2018 07:16:02.189 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 27277 ms

solr6_1     | 2018-05-23 07:16:02.717 WARN  (Thread-12) [   x:alfresco] o.a.s.h.c.AlfrescoSolrClusteringComponent No default engine for document clustering.

solr6_1     | 2018-05-23 07:16:03.890 WARN  (Thread-12) [   x:archive] o.a.s.h.c.AlfrescoSolrClusteringComponent No default engine for document clustering.

alfresco_1  | 2018-05-23 07:16:10,967  INFO  [domain.schema.SchemaBootstrap] [localhost-startStop-1] Ignoring script patch (post-Hibernate): patch.db-V4.2-metadata-query-indexes

alfresco_1  |  2018-05-23 07:16:10,969  INFO  [domain.schema.SchemaBootstrap] [localhost-startStop-1] Ignoring script patch (post-Hibernate): patch.db-V5.1-metadata-query-indexes

alfresco_1  |  2018-05-23 07:16:10,969  INFO  [domain.schema.SchemaBootstrap] [localhost-startStop-1] Ignoring script patch (post-Hibernate): patch.db-V5.2-remove-jbpm-tables-from-db

alfresco_1  |  2018-05-23 07:16:11,335  INFO  [alfresco.repo.admin] [localhost-startStop-1] Using database URL 'jdbc:postgresql://postgres:5432/alfresco' with user 'alfresco'.

alfresco_1  |  2018-05-23 07:16:11,336  INFO  [alfresco.repo.admin] [localhost-startStop-1] Connected to database PostgreSQL version 10.1

alfresco_1  |  2018-05-23 07:16:18,048  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'Authentication' subsystem, ID: [Authentication, managed, alfrescoNtlm1]

alfresco_1  |  2018-05-23 07:16:18,198  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'Authentication' subsystem, ID: [Authentication, managed, alfrescoNtlm1] complete

alfresco_1  |  2018-05-23 07:16:21,173  INFO  [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor Repository Template Processor for extension ftl

alfresco_1  |  2018-05-23 07:16:21,179  INFO  [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor Repository Script Processor for extension js

alfresco_1  |  2018-05-23 07:16:24,280  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'ContentStore' subsystem, ID: [ContentStore, managed, unencrypted]

alfresco_1  |  2018-05-23 07:16:24,315  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'ContentStore' subsystem, ID: [ContentStore, managed, unencrypted] complete

alfresco_1  |  2018-05-23 07:16:24,369  INFO  [domain.schema.SchemaBootstrap] [localhost-startStop-1] Connecting to database: jdbc:postgresql://postgres:5432/alfresco, UserName=alfresco, PostgreSQL JDBC Driver

alfresco_1  |  2018-05-23 07:16:24,370  INFO  [domain.schema.SchemaBootstrap] [localhost-startStop-1] Schema managed by database dialect org.alfresco.repo.domain.dialect.PostgreSQLDialect.

alfresco_1  |  2018-05-23 07:16:24,507  WARN  [domain.schema.SchemaBootstrap] [localhost-startStop-1] Schema validation found 85 potential problems, results written to: /usr/local/tomcat/temp/Alfresco/Alfresco-PostgreSQLDialect-Validation-Pre-Upgrade-alf_-1930649379894062897.txt

 

...

alfresco_1  |  2018-05-23 07:16:33,528  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'Search' subsystem, ID: [Search, managed, solr6]

alfresco_1  |  2018-05-23 07:16:33,902  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'Search' subsystem, ID: [Search, managed, solr6] complete

alfresco_1  |  2018-05-23 07:16:37,234  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'thirdparty' subsystem, ID: [thirdparty, default]

alfresco_1  |  2018-05-23 07:16:37,322  INFO  [transform.pdfrenderer.AlfrescoPdfRendererContentTransformerWorker] [localhost-startStop-1] Using Alfresco PDF Renderer: Alfresco PDF Renderer Version 1.1 [5b0e0b81dt] 2018-02-20 15:34:00 using Pdfium [e53460ff] 2018-02-19 18:34:00 CEST

alfresco_1  |  2018-05-23 07:16:37,410  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'thirdparty' subsystem, ID: [thirdparty, default] complete

alfresco_1  |  2018-05-23 07:16:37,410  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'OOoJodconverter' subsystem, ID: [OOoJodconverter, default]

alfresco_1  |  May 23, 2018 7:16:37 AM org.artofsolving.jodconverter.office.ProcessPoolOfficeManager <init>

alfresco_1  | INFO: ProcessManager implementation is LinuxProcessManager

alfresco_1  | May 23, 2018 7:16:37 AM org.artofsolving.jodconverter.office.OfficeProcess start

alfresco_1  | INFO: Using original OpenOffice command: [/opt/libreoffice5.4/program/soffice.bin, -accept=socket,host=127.0.0.1,port=8100;urp;, -env:UserInstallation=file:///usr/local/tomcat/temp/.jodconverter_socket_host-127.0.0.1_port-8100, -headless, -nocrashreport, -nodefault, -nofirststartwizard, -nolockcheck, -nologo, -norestore]

alfresco_1  | May 23, 2018 7:16:37 AM org.artofsolving.jodconverter.office.OfficeProcess start

alfresco_1  | INFO: starting process with acceptString 'socket,host=127.0.0.1,port=8100,tcpNoDelay=1' and profileDir '/usr/local/tomcat/temp/.jodconverter_socket_host-127.0.0.1_port-8100'

alfresco_1  | May 23, 2018 7:16:37 AM org.artofsolving.jodconverter.office.OfficeProcess start

alfresco_1  | INFO: started process; pid = 81

alfresco_1  | May 23, 2018 7:16:39 AM org.artofsolving.jodconverter.office.ManagedOfficeProcess$6 attempt

alfresco_1  | WARNING: office process died with exit code 81; restarting it

alfresco_1  | May 23, 2018 7:16:39 AM org.artofsolving.jodconverter.office.OfficeProcess start

alfresco_1  | INFO: Using original OpenOffice command: [/opt/libreoffice5.4/program/soffice.bin, -accept=socket,host=127.0.0.1,port=8100;urp;, -env:UserInstallation=file:///usr/local/tomcat/temp/.jodconverter_socket_host-127.0.0.1_port-8100, -headless, -nocrashreport, -nodefault, -nofirststartwizard, -nolockcheck, -nologo, -norestore]

alfresco_1  | May 23, 2018 7:16:39 AM org.artofsolving.jodconverter.office.OfficeProcess start

alfresco_1  | INFO: starting process with acceptString 'socket,host=127.0.0.1,port=8100,tcpNoDelay=1' and profileDir '/usr/local/tomcat/temp/.jodconverter_socket_host-127.0.0.1_port-8100'

alfresco_1  | May 23, 2018 7:16:39 AM org.artofsolving.jodconverter.office.OfficeProcess start

alfresco_1  | INFO: started process; pid = 92

alfresco_1  | May 23, 2018 7:16:39 AM org.artofsolving.jodconverter.office.OfficeConnection connect

alfresco_1  | INFO: connected: 'socket,host=127.0.0.1,port=8100,tcpNoDelay=1'

alfresco_1  | 2018-05-23 07:16:40,021  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'OOoJodconverter' subsystem, ID: [OOoJodconverter, default] complete

alfresco_1  |  2018-05-23 07:16:40,025  WARN  [repo.admin.ConfigurationChecker] [localhost-startStop-1] The 'dir.root' property is set to a relative path './alf_data'.  'dir.root' should be overridden to point to a specific folder.

alfresco_1  |  2018-05-23 07:16:40,026  INFO  [repo.admin.ConfigurationChecker] [localhost-startStop-1] The root data directory ('dir.root') is: ./alf_data

alfresco_1  |  2018-05-23 07:16:40,042  INFO  [admin.patch.PatchExecuter] [localhost-startStop-1] Checking for patches to apply ...

alfresco_1  |  2018-05-23 07:16:40,172  WARN  [admin.patch.PatchExecuter] [localhost-startStop-1] Patch description is not available: Patch[ id=patch.contentFormFolderType, description=patch.contentFormFolderType.description, fixesFromSchema=0, fixesToSchema=36, targetSchema=37, ignored=false]

alfresco_1  |  2018-05-23 07:16:40,199  WARN  [admin.patch.PatchExecuter] [localhost-startStop-1] Patch description is not available: Patch[ id=patch.redeploySubmitProcess, description=patch.redeploySubmitProcess.description, fixesFromSchema=0, fixesToSchema=57, targetSchema=58, ignored=false]

alfresco_1  |  2018-05-23 07:16:40,722  INFO  [admin.patch.PatchExecuter] [localhost-startStop-1] Applying patch 'patch.exampleJavaScript' (Loads sample Javascript file into datadictionary scripts folder).

alfresco_1  |  2018-05-23 07:16:40,764  INFO  [admin.patch.PatchExecuter] [localhost-startStop-1] Applying patch 'patch.siteLoadPatch.swsdp' (Loads a sample site into the repository.).

alfresco_1  |  2018-05-23 07:16:40,840  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'sysAdmin' subsystem, ID: [sysAdmin, default]

alfresco_1  |  2018-05-23 07:16:40,865  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'sysAdmin' subsystem, ID: [sysAdmin, default] complete

 

...

alfresco_1  |  2018-05-23 07:16:44,159  INFO  [repo.module.ModuleServiceImpl] [localhost-startStop-1] Found 4 module package(s).

alfresco_1  |  2018-05-23 07:16:44,178  INFO  [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'alfresco-aos-module' version 1.2.0-RC2.

alfresco_1  |  2018-05-23 07:16:44,197  INFO  [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'org.alfresco.integrations.google.docs' version 3.1.0-RC1.

alfresco_1  |  2018-05-23 07:16:44,221  INFO  [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'alfresco-share-services' version 6.0.0.

alfresco_1  |  2018-05-23 07:16:44,243  INFO  [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'alfresco-trashcan-cleaner' version 2.3.

alfresco_1  |  2018-05-23 07:16:44,264  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'fileServers' subsystem, ID: [fileServers, default]

alfresco_1  |  2018-05-23 07:16:44,759  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'fileServers' subsystem, ID: [fileServers, default] complete

alfresco_1  |  2018-05-23 07:16:44,760  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'imap' subsystem, ID: [imap, default]

alfresco_1  |  2018-05-23 07:16:44,898  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'imap' subsystem, ID: [imap, default] complete

alfresco_1  |  2018-05-23 07:16:44,898  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'email' subsystem, ID: [email, outbound]

alfresco_1  |  2018-05-23 07:16:45,075  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'email' subsystem, ID: [email, outbound] complete

alfresco_1  |  2018-05-23 07:16:45,075  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'email' subsystem, ID: [email, inbound]

alfresco_1  |  2018-05-23 07:16:45,135  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'email' subsystem, ID: [email, inbound] complete

alfresco_1  |  2018-05-23 07:16:45,135  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'Subscriptions' subsystem, ID: [Subscriptions, default]

alfresco_1  |  2018-05-23 07:16:45,159  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'Subscriptions' subsystem, ID: [Subscriptions, default] complete

alfresco_1  |  2018-05-23 07:16:45,189  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'Synchronization' subsystem, ID: [Synchronization, default]

alfresco_1  |  2018-05-23 07:16:45,336  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'Synchronization' subsystem, ID: [Synchronization, default] complete

alfresco_1  |  2018-05-23 07:16:45,354  INFO  [service.descriptor.DescriptorService] [localhost-startStop-1] Alfresco JVM - v1.8.0_161-b12; maximum heap size 878.500MB

alfresco_1  |  2018-05-23 07:16:45,355  INFO  [service.descriptor.DescriptorService] [localhost-startStop-1] Server Mode :UNKNOWN

alfresco_1  |  2018-05-23 07:16:45,359  INFO  [service.descriptor.DescriptorService] [localhost-startStop-1] Alfresco Content Services started (Community Early Access). Current version: 6.0.5 (r1c848a2d-b73) schema 10,201. Originally installed version: 6.0.5 (r1c848a2d-b73) schema 10,201.

alfresco_1  |  2018-05-23 07:16:45,374  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'ActivitiesFeed' subsystem, ID: [ActivitiesFeed, default]

alfresco_1  |  2018-05-23 07:16:45,733  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'ActivitiesFeed' subsystem, ID: [ActivitiesFeed, default] complete

alfresco_1  |  2018-05-23 07:16:45,734  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'Replication' subsystem, ID: [Replication, default]

alfresco_1  |  2018-05-23 07:16:45,779  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'Replication' subsystem, ID: [Replication, default] complete

alfresco_1  |  2018-05-23 07:16:46,914  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Starting 'googledocs' subsystem, ID: [googledocs, drive]

alfresco_1  |  2018-05-23 07:16:47,053  INFO  [management.subsystems.ChildApplicationContextFactory] [localhost-startStop-1] Startup of 'googledocs' subsystem, ID: [googledocs, drive] complete

alfresco_1  |  2018-05-23 07:16:50,438  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 396 Web Scripts (+0 failed), 543 URLs

alfresco_1  |  2018-05-23 07:16:50,445  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 1 Package Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:50,445  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 0 Schema Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,235  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 396 Web Scripts (+0 failed), 543 URLs

alfresco_1  |  2018-05-23 07:16:51,235  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 1 Package Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,236  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 0 Schema Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,240  INFO  [extensions.webscripts.AbstractRuntimeContainer] [localhost-startStop-1] Initialised Repository Web Script Container (in 3933.765ms)

alfresco_1  |  2018-05-23 07:16:51,284  INFO  [extensions.webscripts.TemplateProcessorRegistry] [localhost-startStop-1] Registered template processor freemarker for extension ftl

alfresco_1  |  2018-05-23 07:16:51,296  INFO  [extensions.webscripts.ScriptProcessorRegistry] [localhost-startStop-1] Registered script processor javascript for extension js

alfresco_1  |  2018-05-23 07:16:51,833  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 396 Web Scripts (+0 failed), 543 URLs

alfresco_1  |  2018-05-23 07:16:51,833  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 1 Package Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,834  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 0 Schema Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,914  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 14 Web Scripts (+0 failed), 103 URLs

alfresco_1  |  2018-05-23 07:16:51,914  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 0 Package Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,915  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 0 Schema Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,967  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 14 Web Scripts (+0 failed), 103 URLs

alfresco_1  |  2018-05-23 07:16:51,967  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 0 Package Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,967  INFO  [extensions.webscripts.DeclarativeRegistry] [localhost-startStop-1] Registered 0 Schema Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,969  INFO  [extensions.webscripts.AbstractRuntimeContainer] [localhost-startStop-1] Initialised Public Api Web Script Container (in 631.7979ms)

alfresco_1  |  2018-05-23 07:16:51,993  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 14 Web Scripts (+0 failed), 103 URLs

alfresco_1  |  2018-05-23 07:16:51,993  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 0 Package Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:51,993  INFO  [extensions.webscripts.DeclarativeRegistry] [asynchronouslyRefreshedCacheThreadPool1] Registered 0 Schema Description Documents (+0 failed)

alfresco_1  |  2018-05-23 07:16:52,105  WARN  [scripts.servlet.X509ServletFilterBase] [localhost-startStop-1] clientAuth does not appear to be set for Tomcat. clientAuth must be set to 'want' for X509 Authentication

alfresco_1  |  2018-05-23 07:16:52,105  WARN  [scripts.servlet.X509ServletFilterBase] [localhost-startStop-1] Attempting to set clientAuth=want through JMX...

alfresco_1  |  2018-05-23 07:16:52,117  WARN  [scripts.servlet.X509ServletFilterBase] [localhost-startStop-1] Unable to set clientAuth=want through JMX.

alfresco_1  |  23-May-2018 07:16:56.806 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/alfresco] has finished in [72,893] ms

alfresco_1  | 23-May-2018 07:16:56.815 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]

alfresco_1  | 23-May-2018 07:16:56.831 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]

alfresco_1  | 23-May-2018 07:16:56.841 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 79493 ms

share_1     | 2018-05-23 07:17:05,651  INFO  [web.site.EditionInterceptor] [http-nio-8080-exec-3] Successfully retrieved license information from Alfresco.

alfresco_1  | 2018-05-23 07:17:20,434  INFO  [management.subsystems.ChildApplicationContextFactory] [http-nio-8080-exec-1] Starting 'Transformers' subsystem, ID: [Transformers, default]

alfresco_1  |  2018-05-23 07:17:20,845  INFO  [management.subsystems.ChildApplicationContextFactory] [http-nio-8080-exec-1] Startup of 'Transformers' subsystem, ID: [Transformers, default] complete

share_1     |  2018-05-23 07:17:29,731  INFO  [web.scripts.ImapServerStatus] [http-nio-8080-exec-10] Successfully retrieved IMAP server status from Alfresco: disabled

As we can see, the logs from each container are available as an aggregated console log so we can follow exactly what is happening. Note the AMPs that are applied by default: Alfresco AOS Service, Google Docs Integration, Alfresco Share Services, and the Trashcan Cleaner.

Accessing the Alfresco Share web application

We can now access the Web UI at http://localhost:8080/share. The login credentials are: admin/admin.

Inspecting the Docker Compose file

We have seen how easy it is to deploy and run the ACS system with Docker Compose, next we will look at the Compose YAML file that made it happen. It’s located in the acs-community-deployment/docker-compose directory and looks like the following:

 

version: "3"

services:
alfresco:
image: alfresco/alfresco-content-repository-community:6.0.5-ea
environment:
JAVA_OPTS : "
-Ddb.driver=org.postgresql.Driver
-Ddb.username=alfresco
-Ddb.password=alfresco
-Ddb.url=jdbc:postgresql://postgres:5432/alfresco
-Dsolr.host=solr6
-Dsolr.port=8983
-Dsolr.secureComms=none
-Dsolr.base.url=/solr
-Dindex.subsystem.name=solr6
-Ddeployment.method=DOCKER_COMPOSE
"
ports:
- 8082:8080 #Browser port

share:
image: alfresco/alfresco-share:6.0.a
environment:
- REPO_HOST=alfresco
- REPO_PORT=8080
ports:
- 8080:8080

postgres:
image: postgres:10.1
environment:
- POSTGRES_PASSWORD=alfresco
- POSTGRES_USER=alfresco
- POSTGRES_DB=alfresco
ports:
- 5432:5432

solr6:
image: alfresco/alfresco-search-services:1.1.1
environment:
#Solr needs to know how to register itself with Alfresco
- SOLR_ALFRESCO_HOST=alfresco
- SOLR_ALFRESCO_PORT=8080
#Alfresco needs to know how to call solr
- SOLR_SOLR_HOST=solr6
- SOLR_SOLR_PORT=8983
#Create the default alfresco and archive cores
- SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive
ports:
- 8083:8983 #Browser port

Image configuration

The image property tells Docker Compose what Docker Image to fetch, what version, and from where. If it just specifies the image name and version, as in the above specification, then the images are assumed to reside in https://hub.docker.com. If the image property value looks something like quay.io/alfresco/alfresco-content-services:latest, then it is most likely an Enterprise Edition image and you will need to login to get that.

 

At the end of the image property value is the version specification. You can update the version to fit your requirements. Browse Docker Hub for available versions. It is quite easy to list available versions for Alfresco images, or tags as Docker Hub calls them, with a URL like https://hub.docker.com/r/<user>/<image name>/tags/. To list the available Alfresco Search Services image versions/tags use https://hub.docker.com/r/alfresco/alfresco-search-services/tags/:

 

Environment configuration

The environment property is used to configure the container. For example, it can be used to configure the Repository container with the location of the database and where the Solr server is running. It can also be used to tell the Share container about the location of the Repository server. The Solr and Database containers are also configured using this property.

 

We can look at the environment property configuration and see what properties we can use when starting the containers manually, which is what we will be doing in the next section.

Networking

By default Docker Compose sets up a single network for our ACS solution. Each container for a service joins the default network and is both reachable by other containers on that network, and discoverable by them at a hostname identical to the container name. For example, the Repo container knows about the Database and Solr containers via the following configuration:

 

-Ddb.url=jdbc:postgresql://postgres:5432/alfresco
-Dsolr.host=solr6

 

Where postgres and solr6 are the container names for those services.

Listing Docker images and containers

When you are using Docker for deployment it’s good to know how to list the local images and containers that you are working with.

 

To list images that have been downloaded to your computer:

 

$ docker image ls

REPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE

alfresco/alfresco-content-repository-community   6.0.5-ea            cacbb9510bfe        4 weeks ago         1.72GB

 

alfresco/alfresco-search-services                1.1.1               d6e6a058b986        6 weeks ago         890MB

alfresco/alfresco-share                          6.0.a               9aaa0425fc95        8 weeks ago         709MB

alfresco/alfresco-search-services                1.1.0               56575d75dd82        3 months ago        884MB

postgres                                         10.1                ec61d13c8566        5 months ago        287MB

Here we can see the Alfresco images that were downloaded from Docker Hub when we kicked off the ACS solution with Docker Compose. 

To list running and stopped containers (if you leave out -a, then you will see only running containers):

mbergljung$ docker container ls -a

CONTAINER ID        IMAGE                                                     COMMAND                  CREATED             STATUS                      PORTS                    NAMES

18d33e6734ac        alfresco/alfresco-share:6.0.a                             "/usr/local/tomcat/s…"   21 minutes ago      Up About a minute           0.0.0.0:8080->8080/tcp   dockercompose_share_1

04e553c18cc6        postgres:10.1                                             "docker-entrypoint.s…"   21 minutes ago      Up About a minute           0.0.0.0:5432->5432/tcp   dockercompose_postgres_1

c7f1baae3b55        alfresco/alfresco-search-services:1.1.1                   "/opt/alfresco-searc…"   21 minutes ago      Up About a minute           0.0.0.0:8083->8983/tcp   dockercompose_solr6_1

556e87db8438        alfresco/alfresco-content-repository-community:6.0.5-ea   "catalina.sh run"        21 minutes ago      Up About a minute           0.0.0.0:8082->8080/tcp   dockercompose_alfresco_1

 

d0b6270afeeb        alfresco/alfresco-search-services:1.1.0                   "/opt/alfresco-searc…"   5 weeks ago         Exited (255) 4 weeks ago    0.0.0.0:8983->8983/tcp   alf-search

64d5c9ac4005        postgres:10.1                                             "docker-entrypoint.s…"   5 weeks ago         Exited (255) 4 weeks ago    0.0.0.0:5432->5432/tcp   alf-postgres

062598c1feab        zeppelin:1.0.0-EA                                         "/usr/bin/tini -- bi…"   2 months ago        Exited (255) 2 months ago   0.0.0.0:80->9090/tcp     zeppelin

4eb93b7a4101        alfresco/process-services:1.7.0                           "/root/entrypoint.sh"    4 months ago        Exited (137) 4 months ago                            aps170

3721d2d8bf0f        sonatype/nexus3                                           "sh -c ${SONATYPE_DI…"   4 months ago        Exited (255) 4 months ago   0.0.0.0:8081->8081/tcp   nexus

 

Note how all containers started by Docker Compose will be named as dockercompose_<docker compose file service name>_<instance number>.

Stopping the ACS solution

You can stop all the containers by pressing Ctrl+C at the console (or from another shell you can do docker-compose down). 

 

Here is how it looks like when doing Ctrl-C:

 

...

alfresco_1  | 05-Apr-2018 07:29:21.043 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]

alfresco_1  | 05-Apr-2018 07:29:21.054 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]

alfresco_1  | 05-Apr-2018 07:29:21.056 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 51634 ms

alfresco_1  | 2018-04-05 07:29:21,209  INFO [management.subsystems.ChildApplicationContextFactory] [http-nio-8080-exec-1] Starting 'Search' subsystem, ID: [Search, managed, solr6]

alfresco_1  | 2018-04-05 07:29:21,573  INFO [management.subsystems.ChildApplicationContextFactory] [http-nio-8080-exec-1] Startup of 'Search' subsystem, ID: [Search, managed, solr6] complete

share_1     | 2018-04-05 07:29:36,290  INFO [web.site.EditionInterceptor] [http-nio-8080-exec-3] Successfully retrieved license information from Alfresco.

share_1     | 2018-04-05 07:29:54,625  INFO [web.scripts.ImapServerStatus] [http-nio-8080-exec-9] Successfully retrieved IMAP server status from Alfresco: disabled

share_1     | 2018-04-05 07:30:11,807  INFO [web.scripts.DictionaryQuery] [http-nio-8080-exec-1] Successfully retrieved Data Dictionary from Alfresco.

 

^CGracefully stopping... (press Ctrl+C again to force)

Stopping dockercompose_alfresco_1 ... done

Stopping dockercompose_postgres_1 ... done

Stopping dockercompose_solr6_1    ... done

Stopping dockercompose_share_1    ... done

There is a big difference between doing Ctrl-C and doing docker-compose down. The latter one also removes the containers and any content created:

$ docker-compose down

Stopping dockercompose_share_1    ... done

Stopping dockercompose_postgres_1 ... done

Stopping dockercompose_solr6_1    ... done

Stopping dockercompose_alfresco_1 ... done

Removing dockercompose_share_1    ... done

Removing dockercompose_postgres_1 ... done

Removing dockercompose_solr6_1    ... done

Removing dockercompose_alfresco_1 ... done

To check there are no containers running:

$ docker container ls

CONTAINER ID        IMAGE COMMAND             CREATED STATUS PORTS               NAMES

To list the stopped containers (you will only see these if you did Ctrl-C to stop):

$ docker container ls -a

CONTAINER ID        IMAGE                                      COMMAND CREATED STATUS                PORTS NAMES

e5a1c8a74a75        alfresco/alfresco-content-repository-community:6.0.5-ea   "catalina.sh run" 41 hours ago Exited (143) 4 minutes ago                            dockercompose_alfresco_1

ae1e982c13d5        postgres:10.1                                      "docker-entrypoint.s…" 41 hours ago Exited (0) 4 minutes ago                              dockercompose_postgres_1

b67a5c11215f        alfresco/alfresco-search-services:1.1.0                   "/opt/alfresco-searc…" 41 hours ago Exited (143) 4 minutes ago                            dockercompose_solr6_1

1c372a4cac98        alfresco/alfresco-share:6.0.a                             "/usr/local/tomcat/s…" 41 hours ago Exited (137) 4 minutes ago                            dockercompose_share_1

Removing/Uninstalling the ACS solution

When we are finished with the demo, test, PoC, or whatever we were doing, then we can remove the ACS solution from the computer in an easy way with the following Docker Compose command (this is not necessary if you did docker-compose down):

 

docker-compose mbergljung$ docker-compose rm

Going to remove dockercompose_alfresco_1, dockercompose_postgres_1, dockercompose_solr6_1, dockercompose_share_1

Are you sure? [yN] y

Removing dockercompose_alfresco_1 ... done

Removing dockercompose_postgres_1 ... done

Removing dockercompose_solr6_1    ... done

Removing dockercompose_share_1    ... done

List the running and stopped containers to make sure they are gone:

$ docker container ls -a

CONTAINER ID        IMAGE              COMMAND CREATED           STATUS PORTS        NAMES

Deploying the ACS system Container by Container

Docker Compose is a convenient way of getting an ACS system up and running quickly for testing and PoC purposes. It does however hide all the details about starting and stopping the Docker container. For our purposes it is useful to be able to configure and deploy each container individually because it allows us to get a bit more detail about how Docker works.

 

We are going to deploy and run the same thing we did via the Docker Compose file. But now we are going to start and configure each container manually.

Create a network for the containers

Before we can start any containers we need to create a network for them to communicate over. We need to do this because you can’t use localhost inside a container to connect to another container. We can then connect to this new network when we create a new container.

 

Create a new network called alf-net as follows:

 

$ docker network create alf-net

3393bff64289dffae0e36fde8c7b32c51160b565afd376598c9d191d91d42b32

The response is the long ID for the new network. But we will refer to it as alf-net.

Deploy and Run the Database container

The Alfresco Repo is going to connect to a PostgreSQL database called ‘alfresco’ where the Repository can store the metadata for the content files. We can easily fire up a PostgreSQL database with images available at https://hub.docker.com/_/postgres/.

 

We know from the Docker Compose file what environment variables we can use to configure the database image. Deploy it as follows and give the new container the name alf-postgres (if you already have a container with this name then pick another name, or you can remove the container with the following command if you don’t need to keep it: $ docker container rm alf-postgres):

 

$ docker run --network alf-net --name alf-postgres -p 5432:5432 -e POSTGRES_USER=alfresco -e POSTGRES_PASSWORD=alfresco -e POSTGRES_DB=alfresco -d postgres:10.1  

0f5394598a21c095784646664244d2edb4a13dcda1c4aecfaf7a62e836f6d4c0

 

The --networkoption must be specified directly after run. It cannot, for example, be at the end of the command.

 

Here we start a PostgreSQL container with user/pwd alfresco/alfresco and tell it to create the default database with the name alfresco, which is what the repository needs. The database server is available externally on port 5432. We also connect the container to the alf-net network we created earlier on. The command returns the new container’s ID.

 

Test that it all worked by logging into the container and accessing the database (note that we use the short ID for the container):

 

$ docker container ls

CONTAINER ID        IMAGE COMMAND                  CREATED STATUS PORTS                    NAMES

0f5394598a21        postgres:10.1 "docker-entrypoint.s…"   About a minute ago Up About a minute 0.0.0.0:5432->5432/tcp   alf-postgres

 

$ docker container exec -it 0f5394598a21 /bin/bash

root@0f5394598a21:/# psql alfresco alfresco

psql (10.1)

Type "help" for help.

 

alfresco=# \q

root@0f5394598a21:/# exit

exit

Check that the Database container is connected to the network

At this point it might be a good idea to check that the PostgreSQL database container is actually connected to the custom network alf-net that we created.

 

To check the network use the following command:

 

$ docker network inspect alf-net

[

   {

       "Name": "alf-net",

       "Id": "3393bff64289dffae0e36fde8c7b32c51160b565afd376598c9d191d91d42b32",

       "Created": "2018-04-04T14:00:57.557180066Z",

       "Scope": "local",

       "Driver": "bridge",

       "EnableIPv6": false,

       "IPAM": {

           "Driver": "default",

           "Options": {},

           "Config": [

               {

                   "Subnet": "172.21.0.0/16",

                   "Gateway": "172.21.0.1"

               }

           ]

       },

       "Internal": false,

       "Attachable": false,

       "Ingress": false,

       "ConfigFrom": {

           "Network": ""

       },

       "ConfigOnly": false,

       "Containers": {

           "5661dc60a832e7c620842f88d8107d55546fc9a76e63005b73b8c799db562384": {

               "Name": "alf-postgres",

               "EndpointID": "24a246b1007d7f704dab4cf6ab343b9755e5cfda114692b4176e526a756e04d4",

               "MacAddress": "02:42:ac:15:00:02",

               "IPv4Address": "172.21.0.2/16",

               "IPv6Address": ""

           }

       },

       "Options": {},

       "Labels": {}

   }

]

As we can see, the database container is available on the network on IP 172.21.0.2. We will be able to access the database container under a hostname that is the same as the container name alf-postgres.

Deploy and Run the Alfresco Search Services container

The Alfresco Repo is going to use the Search Services with Apache Solr 6.0 for all search related features. The alfresco/alfresco-search-services image is available for us on Docker Hub. Kick it off as follows and give the new container the name alf-search:

 

$ docker run --network alf-net --name alf-search -p 8983:8983 -e SOLR_ALFRESCO_HOST=alf-repo -e SOLR_ALFRESCO_PORT=8080 -e SOLR_SOLR_HOST=alf-search -e SOLR_SOLR_PORT=8983 -e SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive -d alfresco/alfresco-search-services:1.1.1 

2cc7fda1f64385ee028ad486210544ed708900099431574b6e11fba3358cd6e6

 

There are a number of environment variables we need to pass to the container. The first two tells Apache Solr where Alfresco Repo is running so it can call back for text content. The next two just tells Solr itself where it is running. And the last variable tells Solr to create two cores (i.e. indexes) for live content (alfresco) and archived content (archive).

 

The container will run on the standard Solr port 8983.

 

Now review the logs:

 

$ docker container logs 2cc7fda1f64385ee028ad486210544ed708900099431574b6e11fba3358cd6e6

2018-04-04 15:10:17.370 INFO  (main) [ ] o.e.j.s.Server jetty-9.3.8.v20160314

2018-04-04 15:10:17.756 INFO  (main) [ ] o.a.s.s.SolrDispatchFilter  ___ _ Welcome to Apache Solr? version 6.3.0

2018-04-04 15:10:17.757 INFO  (main) [ ] o.a.s.s.SolrDispatchFilter / __| ___| |_ _   Starting in standalone mode on port 8983

2018-04-04 15:10:17.757 INFO  (main) [ ] o.a.s.s.SolrDispatchFilter \__ \/ _ \ | '_|  Install dir: /opt/alfresco-search-services/solr

2018-04-04 15:10:17.841 INFO  (main) [ ] o.a.s.s.SolrDispatchFilter |___/\___/_|_|    Start time: 2018-04-04T15:10:17.759Z

2018-04-04 15:10:18.699 INFO  (main) [ ] o.e.j.s.ServerConnector Started ServerConnector@4608325d{HTTP/1.1,[http/1.1]}{0.0.0.0:8983}

2018-04-04 15:10:18.699 INFO  (main) [ ] o.e.j.s.Server Started @2098ms

2018-04-04 15:10:30.672 WARN  (Thread-12) [ x:alfresco] o.a.s.h.c.AlfrescoSolrClusteringComponent No default engine for document clustering.

2018-04-04 15:10:31.065 WARN  (Thread-12) [ x:archive] o.a.s.h.c.AlfrescoSolrClusteringComponent No default engine for document clustering.

2018-04-04 15:10:31.536 ERROR (searcherExecutor-7-thread-1-processing-x:alfresco) [   x:alfresco] o.a.s.t.AbstractTracker Model tracking failed

java.net.UnknownHostException: alf-repo

We will see an error when the Search Services are trying to connect to the Alfresco Repository as it is not yet up an running. We will start them next.

Check the Solr UI on http://localhost:8983:

 

 

In the UI we can check that the two cores have been created by clicking on the Core Selector drop down to the left.

Deploy and Run the Alfresco Repository container

The standard Alfresco Repository image (i.e. alfresco.war) is available in Docker Hub under the name alfresco/alfresco-content-repository-community. We want to use the same version of it as was specified in the Docker Compose environment, which was 6.0.4-ea. Start the container as follows and call it alf-repo:

 

$ docker run --network alf-net --name alf-repo -p 8080:8080 -e JAVA_OPTS='-Ddb.driver=org.postgresql.Driver -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.url=jdbc:postgresql://alf-postgres:5432/alfresco -Dsolr.host=alf-search -Dsolr.port=8983 -Dsolr.secureComms=none -Dsolr.base.url=/solr -Dindex.subsystem.name=solr6' -d alfresco/alfresco-content-repository-community:6.0.5-ea

0c3819df858273f5ed55e973a8ef5dbdeeb78f024a3e500334d1bc843c2f6886

 

We publish the Repo on port 8080 instead of port 8082 as in the Docker Compose file. The environment configuration is pretty much taken from the Docker Compose file. The hostnames have been updated to match the container names.

 

Review the logs as follows by using the container ID:

 

$ docker container logs 0c3819df858273f5ed55e973a8ef5dbdeeb78f024a3e500334d1bc843c2f6886

. . .

08-Mar-2018 13:55:38.508 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/alfresco] has finished in [73,821] ms

08-Mar-2018 13:55:38.515 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]

08-Mar-2018 13:55:38.529 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]

08-Mar-2018 13:55:38.535 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 74678 ms

If you see the logs above it means the server has started up properly.

If you are experiencing problems and want to stop and remove the container to be able to start over you can do this by running the following command:

 

$docker container stop alf-repo

alf-repo

$ docker container rm alf-repo

alf-repo

Accessing the Alfresco Repo from a Browser

You should be able to access the Alfresco Repository from a browser. You can test WebDAV access via http://localhost:8080/alfresco/webdav:

 

 

If you are asked to login, use admin/admin.

Deploy and Run the Alfresco Share container

The Alfresco Share container is the last step required for the ACS solution setup and it provides the user interface. The alfresco/alfresco-share image is available for us on Docker Hub. Deploy it as follows and give the new container the name alf-share:

 

$ docker run --network alf-net --name alf-share -p 8081:8080 -e REPO_HOST=alf-repo -e REPO_PORT=8080 -d alfresco/alfresco-share:6.0.a

d9c24489267608d672ff67a30e28d9de5234568be2ea0afe99d9ba037a36674b

 

The only thing we need to tell Share is where the Repo is running. We run Share on port 8081 so it does not clash with the Repo.

 

Now review the logs:

 

$ docker container logs d9c24489267608d672ff67a30e28d9de5234568be2ea0afe99d9ba037a36674b

INFO: Initializing Spring FrameworkServlet 'Spring Surf Dispatcher Servlet'

05-Apr-2018 05:25:15.182 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/share] has finished in [10,485] ms

05-Apr-2018 05:25:15.188 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]

05-Apr-2018 05:25:15.203 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]

05-Apr-2018 05:25:15.207 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 11365 ms

Access the Share UI on http://localhost:8081/share and login with admin/admin:

 

Test the user interface by uploading some files, and searching etc so you can see that it all works properly.

Starting and Stopping the ACS solution

Now we have all the containers that make up the ACS solution running, and we have some new content added to the Repo, let’s stop the containers.

 

To stop the containers, use the following template: docker container stop <name>:

 

$ docker container stop alf-share

alf-share

$ docker container stop alf-repo

alf-repo

$ docker container stop alf-search

alf-search

$ docker container stop alf-postgres

alf-postgres

I stopped them in the opposite order to how they were started.

We can check that they really are stopped by using the following command:

 

$ docker container ls -a

CONTAINER ID        IMAGE                                                     COMMAND                  CREATED              STATUS                        PORTS                    NAMES

6a1b766a01ed        alfresco/alfresco-share:6.0.a                             "/usr/local/tomcat/s…"   About a minute ago   Exited (137) 24 seconds ago                            alf-share

d2d030b10f3f        alfresco/alfresco-content-repository-community:6.0.5-ea   "catalina.sh run"        3 minutes ago        Exited (143) 17 seconds ago                            alf-repo

f95b421ee73c        alfresco/alfresco-search-services:1.1.1                   "/opt/alfresco-searc…"   4 minutes ago        Exited (143) 11 seconds ago                            alf-search

d355deda2b57        postgres:10.1                                             "docker-entrypoint.s…"   5 minutes ago        Exited (0) 6 seconds ago                               alf-postgres

 

Now, let’s start it all up again and see if the content is still there:

$ docker container start alf-postgres

alf-postgres

$ docker container start alf-search

alf-search

$ docker container start alf-repo

alf-repo

$ docker container start alf-share

alf-share

Login to Share and verify that the content is still there. All the content is there and the search index is intact. Next we will look at how this works.

Where is the data stored?

When working with containers there are a couple of ways that data can be persisted. You can just store it inside the container or you can use something called Docker Volumes.

 

Storing it inside a container is a simple approach for demoing, testing, and PoC situations. However, it’s not ideal for a production environment as all content will be inside the container, which will make it very big. This means that there’s no way of having backup containers if something crashes. Also, it would not work if you wanted to cluster ACS. What you would use in production is Docker Volumes, which enable you to store the content outside the container.

 

To look at the Repository content we have to open a shell into the alf-repo container as follows and step into the alf_data directory (note, the container need to be started for this to work):

 

$ docker container exec -it alf-repo /bin/bash

[root@0c3819df8582 tomcat]# ls -l

total 184

-rw-r----- 1 root root 57092 Feb  6 23:12 LICENSE

-rw-r----- 1 root root  1723 Feb 6 23:12 NOTICE

-rw-r----- 1 root root  7138 Feb 6 23:12 RELEASE-NOTES

-rw-r----- 1 root root 16246 Feb  6 23:12 RUNNING.txt

drwxr-x--- 4 root root  4096 Apr 4 15:21 alf_data

drwxr-xr-x 1 root root  4096 Mar 27 13:28 alfresco-mmt

-rw-r----- 1 root root 22382 Apr  5 05:42 alfresco.log

-rw-r----- 1 root root 23311 Apr  4 15:22 alfresco.log.2018-04-04

drwxr-xr-x 1 root root  4096 Mar 27 13:28 amps

drwxr-x--- 2 root root  4096 Mar 26 11:14 bin

drwx------ 1 root root  4096 Apr 4 15:20 conf

drwxr-xr-x 3 root root  4096 Mar 26 11:14 include

drwxr-x--- 1 root root  4096 Mar 27 13:28 lib

drwxr-x--- 1 root root  4096 Apr 5 05:41 logs

drwxr-xr-x 3 root root  4096 Mar 26 11:14 native-jni-lib

drwxr-xr-x 1 root root  4096 Mar 27 13:28 shared

drwxr-x--- 1 root root  4096 Apr 5 05:42 temp

drwxr-x--- 1 root root  4096 Apr 4 15:20 webapps

drwxr-x--- 1 root root  4096 Apr 4 15:20 work

[root@0c3819df8582 tomcat]# cd alf_data/

[root@0c3819df8582 alf_data]# ls -l

total 8

drwxr-x--- 3 root root 4096 Apr  4 15:21 contentstore

drwxr-x--- 2 root root 4096 Apr  4 15:20 contentstore.deleted

[root@0c3819df8582 alf_data]# cd contentstore

[root@0c3819df8582 contentstore]# cd 2018/4/5/5/33/

[root@0c3819df8582 33]# ls -l

total 8

-rw-r----- 1 root root 3732 Apr  5 05:33 1d41a201-ad12-42f9-9f44-3e70597b5fa4.bin

-rw-r----- 1 root root   61 Apr 5 05:33 b1ba1f0f-db04-49fd-9e11-aa57d2ffc6e6.bin

[root@0c3819df8582 33]# exit

Note that when you do this you will have a different directory structure under contentstore as you will have uploaded content after this article was written.

Removing/Uninstalling the ACS solution

To remove everything from our computer make sure each container is stopped as discussed above. Then use the following template - docker container rm <name>(note, all data will be permanently deleted):

$ docker container rm alf-share

alf-share

$ docker container rm alf-repo

alf-repo

$ docker container rm alf-search

alf-search

$ docker container rm alf-postgres

alf-postgres

I removed them in the opposite order to how they were started.

Summary

Deploying and running an ACS solution by starting each container individually is a bit more work. But we were able to learn much more about how things work in a Docker container, and we got to know how to set up a network for the containers to communicate over.

 

However, when you want to get an ACS environment up a running for testing or a PoC project, it is probably more efficient to use Docker Compose.

Building and Deploying custom ACS Images

So far we have looked at how to run the standard ACS solution without any customizations. I’m sure you have customizations that you want to include in your ACS solution, such as a custom domain specific content model. Next we will look at how you build customizations for ACS 6.0.

 

The source code for this section can be downloaded and cloned from here.

Prerequisites

In order to build the projects discussed in this section you will need to have Java and Maven installed. See the instructions at the beginning of this page.

 

You will also need to update your Maven settings file (located at ~/.m2/settings.xml) with the location of the public Alfresco Nexus Repository:

 

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
https://maven.apache.org/xsd/settings-1.0.0.xsd"
>

<profiles>
<profile>
<id>alfresco.default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>alfresco-public</id>
<url>https://artifacts.alfresco.com/nexus/content/groups/public</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>alfresco-public</id>
<name>Alfresco</name>
<url>http://artifacts.alfresco.com/nexus/content/repositories/releases</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
</settings>

 

Building Repository extensions for ACS 6.0

At the moment there is no support for ACS 6.0 in the Alfresco SDK but we can still build extensions. We just have to do a bit of “engineering”. Assuming you have downloaded the source code for this section you will find as part of it a maven project called custom-repo-extension, which is laid out as a standard Alfresco Platform JAR extension.

 

This project contains a simple content model definition and the bootstrapping for it. It also contains a repository action so we can check that it works to compile against the Alfresco classes. This article is not primarily about building Alfresco extensions so I will not explain that code here.

 

The POM file for the project is the important part as it tells us how we can build against ACS 6.0, it looks like this:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.alfresco</groupId>
<artifactId>acs-community-packaging</artifactId>
<version>6.0.5-ea</version>
<relativePath></relativePath>
</parent>

<groupId>org.alfresco.training</groupId>
<artifactId>custom-repo-extension</artifactId>
<version>1.0-SNAPSHOT</version>

<name>Custom repository extension JAR</name>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-repository</artifactId>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

 

The Maven POM file starts off with a definition of a Parent POM. This parent project is part of the acs-community-packaging project that we we cloned in the beginning of this article. If you open it up you will find all kinds of useful property definitions and dependency management declarations, for example:

 

 


<properties>
...
<dependency.alfresco-core.version>7.1</dependency.alfresco-core.version>
<dependency.alfresco-data-model.version>8.3</dependency.alfresco-data-model.version>
<dependency.alfresco-repository.version>6.41</dependency.alfresco-repository.version>
<dependency.alfresco-remote-api.version>6.27</dependency.alfresco-remote-api.version>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-core</artifactId>
<version>${dependency.alfresco-core.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-core</artifactId>
<version>${dependency.alfresco-core.version}</version>
<classifier>tests</classifier>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-data-model</artifactId>
<version>${dependency.alfresco-data-model.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-jlan-embed</artifactId>
<version>${dependency.alfresco-jlan.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-remote-api</artifactId>
<version>${dependency.alfresco-remote-api.version}</version>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-remote-api</artifactId>
<version>${dependency.alfresco-remote-api.version}</version>
<classifier>tests</classifier>
</dependency>
<dependency>
<groupId>org.alfresco</groupId>
<artifactId>alfresco-repository</artifactId>
<version>${dependency.alfresco-repository.version}</version>
</dependency>
...

 

This file contains version properties for the different libraries that are part of ACS 6.0.4-ea. So we don’t have to figure this out. It also contains dependencyManagement configurations for the different libraries that we might depend on when building, so we don’t have to specify versions for those in our project.

 

Our project depends on the alfresco-repository library so we can build the custom repository action. We also filter the resource directory so we can use property substitution variables like this: module.id=${project.artifactId} and have them converted to module.id=custom-repo-extension during the build.

 

Now build the extension:

 

custom-repo-extension mbergljung$ mvn clean install

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building Custom repository extension JAR 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:3.0.0:clean (default-clean) @ custom-repo-extension ---

[INFO] Deleting /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-repo-extension/target

[INFO]

[INFO] --- maven-resources-plugin:3.0.1:resources (default-resources) @ custom-repo-extension ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] Copying 6 resources

[INFO]

[INFO] --- maven-compiler-plugin:3.6.0:compile (default-compile) @ custom-repo-extension ---

[INFO] Changes detected - recompiling the module!

[INFO] Compiling 1 source file to /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-repo-extension/target/classes

[INFO]

[INFO] --- maven-resources-plugin:3.0.1:testResources (default-testResources) @ custom-repo-extension ---

[INFO] Using 'UTF-8' encoding to copy filtered resources.

[INFO] skip non existing resourceDirectory /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-repo-extension/src/test/resources

[INFO]

[INFO] --- maven-compiler-plugin:3.6.0:testCompile (default-testCompile) @ custom-repo-extension ---

[INFO] No sources to compile

[INFO]

[INFO] --- maven-surefire-plugin:2.19.1:test (default-test) @ custom-repo-extension ---

[INFO] No tests to run.

[INFO]

[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ custom-repo-extension ---

[INFO] Building jar: /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-repo-extension/target/custom-repo-extension-1.0-SNAPSHOT.jar

[INFO]

[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ custom-repo-extension ---

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-repo-extension/target/custom-repo-extension-1.0-SNAPSHOT.jar to /Users/mbergljung/.m2/repository/org/alfresco/training/custom-repo-extension/1.0-SNAPSHOT/custom-repo-extension-1.0-SNAPSHOT.jar

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-repo-extension/pom.xml to /Users/mbergljung/.m2/repository/org/alfresco/training/custom-repo-extension/1.0-SNAPSHOT/custom-repo-extension-1.0-SNAPSHOT.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 3.264 s

[INFO] Finished at: 2018-04-06T06:52:08+01:00

[INFO] Final Memory: 42M/339M

[INFO] ------------------------------------------------------------------------

We now have the platform/repo JAR extension in our local Maven repository, ready to be included in a custom Alfresco Repo Image.

Building a custom Repository Image

To build a custom image based on the standard alfresco/alfresco-content-repository-community image we have to create a Dockerfile. We will use a Maven project to bring together all the extensions (both JARs and AMPs) that we want to include in the custom image.

Maven project to assemble all Repository extensions

This project is part of the source code for this article and is called docker-alfresco-custom. It’s used to bring together all the repository extensions that we want to include in the custom Repository image (this Maven project could potentially be used to build the custom image with a plugin such as fabric8io, but this is not covered in this article):

 

The POM looks like this:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.alfresco.training</groupId>
<artifactId>docker-alfresco-custom</artifactId>
<version>1.0-SNAPSHOT</version>
<name>JAR and AMP assembly under /target for use by Dockerfile</name>
<packaging>pom</packaging>

<dependencies>
<dependency>
<groupId>org.alfresco.training</groupId>
<artifactId>custom-repo-extension</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.softwareloop</groupId>
<artifactId>uploader-plus-repo</artifactId>
<version>1.6</version>
<type>amp</type>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-repo-extensions</id>
<phase>process-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.alfresco.training</groupId>
<artifactId>custom-repo-extension</artifactId>
<version>1.0-SNAPSHOT</version>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/jars</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>com.softwareloop</groupId>
<artifactId>uploader-plus-repo</artifactId>
<version>1.6</version>
<type>amp</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/amps</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

 

In the dependencies section we define all the extensions that should be part of our custom repository image. In this case we define a dependency to the custom extension that we built in the previous section, and a dependency to an open source extension that customizes the upload functionality in Alfresco, so you can attach metadata while uploading.

 

The maven-dependency-plugin plugin is used to copy the extensions in under the /target directory. We can then pick them up from there when building the custom repository image.

 

Now build the project:

 

docker-alfresco-custom mbergljung$ mvn clean install

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JAR and AMP assembly under /target for use by Dockerfile 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ docker-alfresco-custom ---

[INFO] Deleting /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-alfresco-custom/target

[INFO]

[INFO] --- maven-dependency-plugin:3.0.2:copy (copy-repo-extensions) @ docker-alfresco-custom ---

[INFO] Configured Artifact: org.alfresco.training:custom-repo-extension:1.0-SNAPSHOT:jar

[INFO] Configured Artifact: com.softwareloop:uploader-plus-repo:1.6:amp

[INFO] Copying custom-repo-extension-1.0-SNAPSHOT.jar to /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-alfresco-custom/target/jars/custom-repo-extension-1.0-SNAPSHOT.jar

[INFO] Copying uploader-plus-repo-1.6.amp to /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-alfresco-custom/target/amps/uploader-plus-repo-1.6.amp

[INFO]

[INFO] --- maven-install-plugin:2.4:install (default-install) @ docker-alfresco-custom ---

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-alfresco-custom/pom.xml to /Users/mbergljung/.m2/repository/org/alfresco/training/docker-alfresco-custom/1.0-SNAPSHOT/docker-alfresco-custom-1.0-SNAPSHOT.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 1.271 s

[INFO] Finished at: 2018-04-06T07:45:33+01:00

[INFO] Final Memory: 12M/309M

[INFO] ------------------------------------------------------------------------

What you end up with is a target directory looking like this:

 

docker-alfresco-custom mbergljung$ tree

.

├── Dockerfile

├── pom.xml

└── target

   ├── amps

   │ └── uploader-plus-repo-1.6.amp

   └── jars

       └── custom-repo-extension-1.0-SNAPSHOT.jar

We can now code the Dockerfile to pick up the extensions from this location.

Create the Dockerfile for custom Repository image build

The Dockerfile that we will use to build our custom Repository is located in the same directory as the POM file that assembles the extensions. It looks like the following:

 

FROM alfresco/alfresco-content-repository-community:6.0.5-ea

ARG TOMCAT_DIR=/usr/local/tomcat

RUN mkdir -p $TOMCAT_DIR/amps

COPY target/amps $TOMCAT_DIR/amps
COPY target/jars $TOMCAT_DIR/webapps/alfresco/WEB-INF/lib

RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install \
$TOMCAT_DIR/amps $TOMCAT_DIR/webapps/alfresco -directory -nobackup -force

 

The first thing it does is define that the new image will be based on the standard alfresco/alfresco-content-repository-community image version 6.0.5-ea that is available in Docker Hub. Then it defines a local variable called TOMCAT_DIR, which points to where in the standard image the Apache Tomcat installation is located. We then make sure that the amps directory exists in the image.

 

The next command in the file is to copy AMPs and JARs into the image. JAR extensions are copied directly into the exploded webapp. AMP extensions are copied into the /amps directory from where they will be picked up by the Module Management Tool (MMT).

 

The last step is to use the MMT tool to apply the AMPs to the exploded webapp.

Currently it does not work to put stuff in the {TOMCAT_DIR}/modules/platform directory. JAR extensions are not picked up from this location at the moment.

Build the custom Repository Docker Image

Now the Dockerfile is ready and the AMP and JAR extensions are available, we can build the custom repository image as follows:

 

docker-alfresco-custom mbergljung$docker build . --tag my-acs-repo:6.0

Sending build context to Docker daemon  41.98kB

Step 1/6 : FROM alfresco/alfresco-content-repository-community:6.0.5-ea

---> df0b08d0d3a3

Step 2/6 : ARG TOMCAT_DIR=/usr/local/tomcat

---> Running in b9da89b41cd7

Removing intermediate container b9da89b41cd7

---> c3379ffbd749

Step 3/6 : RUN mkdir -p $TOMCAT_DIR/amps

---> Running in d5081fd4216c

Removing intermediate container d5081fd4216c

---> b64f819c98f6

Step 4/6 : COPY target/amps $TOMCAT_DIR/amps

---> 69e4c78b184c

Step 5/6 : COPY target/jars $TOMCAT_DIR/webapps/alfresco/WEB-INF/lib

---> 493379108de1

Step 6/6 : RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install               $TOMCAT_DIR/amps $TOMCAT_DIR/webapps/alfresco -directory -nobackup -force

---> Running in e5ed4cb90501

Removing intermediate container e5ed4cb90501

---> 3f4a2d48d03a

Successfully built 3f4a2d48d03a

Successfully tagged my-acs-repo:6.0

We call the custom image my-acs-repo and give it a version tag 6.0.

Verify that we have the new image locally:

$docker image ls

REPOSITORY                                       TAG IMAGE ID CREATED           SIZE

my-acs-repo                                      6.0 b282286605cb 2 minutes ago       1.74GB

alfresco/alfresco-content-repository-community   6.0.5-ea df0b08d0d3a3 8 days ago          1.72GB

alfresco/alfresco-share                          6.0.a 9aaa0425fc95 9 days ago          709MB

alfresco/alfresco-search-services                1.1.1 56575d75dd82 2 months ago        884MB

We can see our image called my-acs-repo and we also have the Docker Hub image that it is based on.

Running a container based on the custom Repository image

We now need to get a container running that is based on our new my-acs-repo image.

The new custom repo image will need a database and search engine so let’s create those first using the standard images as before. We assume here that the alf-net network is still available.

 

Starting with a PostgreSQL container (you might have to stop and remove the container first):

 

$ docker run --network alf-net --name alf-postgres -p 5432:5432 -e POSTGRES_USER=alfresco -e POSTGRES_PASSWORD=alfresco -e POSTGRES_DB=alfresco -d postgres:10.1  

 

And the Alfresco Search Services container (you might have to stop and remove the container first):

 

$ docker run --network alf-net --name alf-search -p 8983:8983 -e SOLR_ALFRESCO_HOST=alf-repo -e SOLR_ALFRESCO_PORT=8080 -e SOLR_SOLR_HOST=alf-search -e SOLR_SOLR_PORT=8983 -e SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive -d alfresco/alfresco-search-services:1.1.1

 

Now let’s start the custom Repo container (you might have to stop and remove the container first):

 

$ docker run --network alf-net --name alf-repo -p 8080:8080 -e JAVA_OPTS='-Ddb.driver=org.postgresql.Driver -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.url=jdbc:postgresql://alf-postgres:5432/alfresco -Dsolr.host=alf-search -Dsolr.port=8983 -Dsolr.secureComms=none -Dsolr.base.url=/solr -Dindex.subsystem.name=solr6' -d my-acs-repo:6.0

d52d18c57d366967f17425771bdc87f5931c2d5b5a6670052ac96b5434152c4a

 

Make sure to use the my-acs-repo:6.0 custom image that we just created. In the logs we should see the new AMP and JAR extension applied:

 

$ docker container logs d52d18c57d366967f17425771bdc87f5931c2d5b5a6670052ac96b5434152c4a

2018-04-06 05:19:31,016  INFO [repo.module.ModuleServiceImpl] [localhost-startStop-1] Found 6 module package(s).

2018-04-06 05:19:31,036  INFO [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'alfresco-aos-module' version 1.1.7.

2018-04-06 05:19:31,065  INFO [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'custom-repo-extension' version 1.0-SNAPSHOT.

2018-04-06 05:19:31,090  INFO [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'org.alfresco.integrations.google.docs' version 3.0.4.2.

2018-04-06 05:19:31,102  INFO [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'uploader-plus-repo' version 1.6.1801311724.

2018-04-06 05:19:31,121  INFO [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'alfresco-share-services' version 6.0.0.

2018-04-06 05:19:31,141  INFO [repo.module.ModuleServiceImpl] [localhost-startStop-1] Installing module 'alfresco-trashcan-cleaner' version 2.3.

...

 

In the log above we can verify that the two extensions (i.e. custom-repo-extension and uploader-plus-repo) we added have been installed successfully.

 

Check that you can access the Repository with http://localhost:8080/alfresco/webdav

Re-Building an Alfresco Repo Image

At some point you have to rebuild a custom image. You might have made a mistake in the first build, or you just want to add more extensions.

 

Start by listing your containers to find out which one is based on the custom image:

 

$ docker container ls

CONTAINER ID        IMAGE                      COMMAND CREATED   STATUS PORTS NAMES

d776612160c3        my-acs-repo:6.0                      "catalina.sh run" 5 minutes ago   Up 5 minutes 0.0.0.0:8080->8080/tcp alf-repo

c6e57ff6ca96        alfresco/alfresco-search-services:1.1.0   "/opt/alfresco-searc…" 17 hours ago   Up 17 hours 0.0.0.0:8983->8983/tcp alf-search

dcf89cd04192        postgres:10.1                      "docker-entrypoint.s…" 17 hours ago   Up 17 hours 0.0.0.0:5432->5432/tcp alf-postgres

Stop and remove the relevant containers:

 

$ docker container stop alf-repo alf-search alf-postgres

alf-repo

alf-search

alf-postgres

$ docker container rm alf-repo alf-search alf-postgres

alf-repo

alf-search

alf-postgres

Here we also remove the database and search containers as they are not in sync when restarting a container based on a new image. Any new content that was previously created will be gone when a new container is created based on a rebuilt image. The search service would still have an index for previous content and the database would still have metadata for previous new content. When developing solutions for ACS 6.0 it is a good idea to work with Docker Volumes as you are likely to have to rebuild the repository image a lot.

List all the images:

 

$ docker image ls

REPOSITORY                                       TAG IMAGE ID CREATED           SIZE

my-acs-repo                                      6.0 c133631019ac 7 minutes ago       1.74GB

alfresco/alfresco-content-repository-community   6.0.4-ea df0b08d0d3a3 9 days ago          1.72GB

alfresco/alfresco-share                          6.0.a 9aaa0425fc95 9 days ago          709MB

alfresco/alfresco-search-services                1.1.0 56575d75dd82 2 months ago        884MB

And remove the image that you plan to update:

 

$ docker image rm my-acs-repo:6.0

After this you will have to build the custom image again and restart the database, search, and repo containers.

Building Share extensions for ACS 6.0

At the moment there is no support for ACS 6.0 in the Alfresco SDK but we can still build extensions. We just have to do a bit of “engineering”. Assuming you have downloaded the source code for this section you will find as part of it a maven project called custom-share-extension, which is laid out as a standard Alfresco Share JAR extension.

This Share extension contains the UI labels, forms, and Advanced search configuration for the Repo extension we developed in the previous section. This article is not primarily about building Alfresco extensions so I will not explain that code here.

 

The POM file for the project is the important part as it tells us how we can build against ACS 6.0, it looks like this:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.alfresco.training</groupId>
<artifactId>custom-share-extension</artifactId>
<version>1.0-SNAPSHOT</version>

<name>Custom share extension JAR</name>
<packaging>jar</packaging>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>

 

The Maven POM file is very straight forward in this case as we just need to package up the files in the src directory. There is no need for any Java file compilation. At the end we also filter the resource directory so we can use property substitution variables like this module.id=${project.artifactId} and have them converted to module.id=custom-share-extension during the build.

 

To build the extension:

 

custom-share-extension mbergljung$ mvn clean install

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building Custom share extension JAR 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ custom-share-extension ---

[INFO]

[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ custom-share-extension ---

[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!

[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!

[INFO] Copying 5 resources

[INFO]

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ custom-share-extension ---

[INFO] No sources to compile

[INFO]

[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ custom-share-extension ---

[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!

[INFO] skip non existing resourceDirectory /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-share-extension/src/test/resources

[INFO]

[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ custom-share-extension ---

[INFO] No sources to compile

[INFO]

[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ custom-share-extension ---

[INFO] No tests to run.

[INFO]

[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ custom-share-extension ---

[INFO] Building jar: /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-share-extension/target/custom-share-extension-1.0-SNAPSHOT.jar

[INFO]

[INFO] --- maven-install-plugin:2.4:install (default-install) @ custom-share-extension ---

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-share-extension/target/custom-share-extension-1.0-SNAPSHOT.jar to /Users/mbergljung/.m2/repository/org/alfresco/training/custom-share-extension/1.0-SNAPSHOT/custom-share-extension-1.0-SNAPSHOT.jar

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-share-extension/pom.xml to /Users/mbergljung/.m2/repository/org/alfresco/training/custom-share-extension/1.0-SNAPSHOT/custom-share-extension-1.0-SNAPSHOT.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 1.160 s

[INFO] Finished at: 2018-04-06T14:56:59+01:00

[INFO] Final Memory: 11M/245M

[INFO] ------------------------------------------------------------------------

We now have a Share JAR extension in our local Maven repository, which is ready to be included in a custom Alfresco Share Image.

Building a custom Share Image

To build a custom image based on the standard alfresco/alfresco-share image we have to create a Dockerfile. But we also have to figure out a way to bring together all the extensions (both JARs and AMPs) that we want to include in the custom image. We can do that with a new Maven project.

Maven project to assemble all Share extensions

This project is part of the source code for this article and is called docker-share-custom. It is used to bring together all the Share extensions that we want to include in the custom Share image (this Maven project could potentially also be used to build the custom image with a plugin such as fabric8io, but this is not covered in this article):.

The POM looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.alfresco.training</groupId>
<artifactId>docker-share-custom</artifactId>
<version>1.0-SNAPSHOT</version>
<name>JAR and AMP assembly under /target for use by Dockerfile</name>
<packaging>pom</packaging>

<dependencies>
<dependency>
<groupId>org.alfresco.training</groupId>
<artifactId>custom-share-extension</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.softwareloop</groupId>
<artifactId>uploader-plus-surf</artifactId>
<version>1.6</version>
<type>amp</type>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-share-extensions</id>
<phase>process-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.alfresco.training</groupId>
<artifactId>custom-share-extension</artifactId>
<version>1.0-SNAPSHOT</version>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/jars</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>com.softwareloop</groupId>
<artifactId>uploader-plus-surf</artifactId>
<version>1.6</version>
<type>amp</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/amps_share</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

 

In the dependencies section we define all the extensions that should be part of our custom Share image. In this case we define a dependency to the custom extension that we built in the previous section, and a dependency to an open source extension that customizes the upload functionality in Alfresco so you can attach metadata while uploading.

 

The maven-dependency-plugin plugin is used to copy the extensions in under the /target directory. We can then pick them up from here when building the custom Share image.

 

To build the project:

 

docker-share-custom mbergljung$ mvn clean install

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building JAR and AMP assembly under /target for use by Dockerfile 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ docker-share-custom ---

[INFO] Deleting /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-share-custom/target

[INFO]

[INFO] --- maven-dependency-plugin:3.0.2:copy (copy-share-extensions) @ docker-share-custom ---

[INFO] Configured Artifact: org.alfresco.training:custom-share-extension:1.0-SNAPSHOT:jar

[INFO] Configured Artifact: com.softwareloop:uploader-plus-surf:1.6:amp

[INFO] Copying custom-share-extension-1.0-SNAPSHOT.jar to /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-share-custom/target/jars/custom-share-extension-1.0-SNAPSHOT.jar

[INFO] Copying uploader-plus-surf-1.6.amp to /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-share-custom/target/amps/uploader-plus-surf-1.6.amp

[INFO]

[INFO] --- maven-install-plugin:2.4:install (default-install) @ docker-share-custom ---

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-share-custom/pom.xml to /Users/mbergljung/.m2/repository/org/alfresco/training/docker-share-custom/1.0-SNAPSHOT/docker-share-custom-1.0-SNAPSHOT.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 0.966 s

[INFO] Finished at: 2018-04-06T15:19:06+01:00

[INFO] Final Memory: 12M/309M

[INFO] ------------------------------------------------------------------------

You now have a target directory that looks like this:

docker-share-custom mbergljung$ tree

.

├── Dockerfile

├── pom.xml

└── target

   ├── amps_share

   │ └── uploader-plus-surf-1.6.amp

   └── jars

       └── custom-share-extension-1.0-SNAPSHOT.jar

We can now code the Dockerfile to pick these extensions up from here.

Create the Dockerfile for custom Share image build

The Dockerfile we will use to build our custom Share image will be located in the same directory as the POM file that assembles the extensions. Here is what it looks like:

 

FROM alfresco/alfresco-share:6.0.a

ARG TOMCAT_DIR=/usr/local/tomcat

RUN mkdir -p $TOMCAT_DIR/amps_share

COPY target/amps_share $TOMCAT_DIR/amps_share
COPY target/jars $TOMCAT_DIR/webapps/share/WEB-INF/lib

RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install \
$TOMCAT_DIR/amps_share $TOMCAT_DIR/webapps/share -directory -nobackup -force

 

The first thing it does is to define that the new image will be based on the standard alfresco/alfresco-share image version 6.0.a that is available in Docker Hub. Then it defines a local variable called TOMCAT_DIR, which points to where in the standard image the Apache Tomcat installation is located. We then make sure that the amps_share directory exists in the image.

 

The next command in the file is to copy AMPs and JARs into the image. JAR extensions are copied directly into the exploded webapp. AMP extensions are copied into the /amps_share directory from where they will be picked up by the Module Management Tool (MMT).

 

The last step is to use the MMT tool to apply the AMPs to the exploded webapp.

Currently it does not work to put stuff in the {TOMCAT_DIR}/modules/share directory. JAR extensions are not picked up from this location at the moment.

Build the custom Share Docker Image

Now when the Dockerfile is ready and the AMP and JAR extensions are available, we can build the custom repository image as follows:

 

docker-share-custom mbergljung$ docker build . --tag my-acs-share:6.0

Sending build context to Docker daemon    108kB

Step 1/6 : FROM alfresco/alfresco-share:6.0.a

---> 9aaa0425fc95

Step 2/6 : ARG TOMCAT_DIR=/usr/local/tomcat

---> Running in 56271fc4b1ff

Removing intermediate container 56271fc4b1ff

---> 91c88b57b1b2

Step 3/6 : RUN mkdir -p $TOMCAT_DIR/amps_share

---> Running in 5287e9a5e61d

Removing intermediate container 5287e9a5e61d

---> 14a48b64c760

Step 4/6 : COPY target/amps_share $TOMCAT_DIR/amps_share

---> 64d5ff319179

Step 5/6 : COPY target/jars $TOMCAT_DIR/webapps/share/WEB-INF/lib

---> 7cf792efec42

Step 6/6 : RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install               $TOMCAT_DIR/amps_share $TOMCAT_DIR/webapps/share -directory -nobackup -force

---> Running in 7a3bbefcaf59

Removing intermediate container 7a3bbefcaf59

---> e760d22a715a

Successfully built e760d22a715a

Successfully tagged my-acs-share:6.0

We call the custom image my-acs-share and give it a version tag 6.0.

Verify that you have the new image locally:

 

$ docker image ls

REPOSITORY                                       TAG IMAGE ID CREATED           SIZE

my-acs-share                                     6.0 e760d22a715a 34 seconds ago      709MB

my-acs-repo                                      6.0 c133631019ac 9 hours ago         1.74GB

alfresco/alfresco-content-repository-community   6.0.4-ea df0b08d0d3a3 10 days ago         1.72GB

alfresco/alfresco-share                          6.0.a 9aaa0425fc95 10 days ago         709MB

alfresco/alfresco-search-services                1.1.0 56575d75dd82 2 months ago        884MB

We can see our image called my-acs-share and we also have the Docker Hub image that it is based on.

Running a container based on the custom Share image

Now we can start a container that is based on our new my-acs-share image. It will depend on the Repository, Search, and Database containers, so make sure they are running. The alf-net network must also still be available.

 

To start the custom Share container:

 

$ docker run --network alf-net --name alf-share -p 8081:8080 -e REPO_HOST=alf-repo -e REPO_PORT=8080 -d my-acs-share:6.0

245ee746cb2d5c28183ab67d97e176ffbe57775cfd13a9237791e53254d19429

 

In the logs we should see the new AMP and JAR extension applied:

 

$ docker container logs 245ee746cb2d5c28183ab67d97e176ffbe57775cfd13a9237791e53254d19429

2018-04-06 14:35:54,268  INFO [config.packaging.ModulePackageManager] [localhost-startStop-1] Found 3 module package(s)

2018-04-06 14:35:54,270  INFO [config.packaging.ModulePackageManager] [localhost-startStop-1] Alfresco / Google Docs Share Module, 3.0.4.2, The Share side artifacts of the Alfresco / Google Docs Integration.

uploader-plus-surf, 1.6.1801311724, uploader-plus AMP for Alfresco Share

Custom share extension JAR, 1.0-SNAPSHOT, ${project.description}

...

 

In the log above we can verify that the two extensions (i.e. Custom share extension JAR and uploader-plus-surf) we added have been installed successfully.

 

Check that you can access the Repository with Alfresco Share at http://localhost:8081/share.

 

Login with admin/admin and upload a document to a folder. Execute the Change Type action and you should see the new content type we added:

 

 

After changing the type you should see a new ACME Doc Information property section:

 

 

You can set the ACME Doc ID by clicking the Edit Properties action:

 

Let’s also test the custom uploader functionality to make sure the extension has been applied properly. The custom upload functionality will not be enabled unless you first make some configurations. Start by configuring a so called “Upload folder” under Admin Tools | Uploader Plus:



 

In this case I have selected a custom folder called Test that is a subfolder of Guest Home. I have then said that only ACME Document type is allowed this folder. It’s then just a matter of uploading something to this folder and the custom Upload Plus dialog will appear:



 

So that seems to work nicely, pretty cool!

Building and Running an Alfresco Repo Image with a data Volume

When we run a container based on the Repository image the Alfresco Data (i.e. alf_data) is stored inside the container. The way this works is that an image is made up of a number of read-only layers. When you start a container based on the Repository image an extra read-write layer will be created on top of it. Then when a file is updated, for example in the tomcat/alf_data directory inside the container, it will automatically be copied into the read-write layer (copy-on-write). A container is Ephemeral (lasts a very short time) and when you remove it the Alfresco data will also be gone as the read-write layer is not persisted outside the container.

 

This presents some problems for us as Alfresco Developers as we would be likely to create new images quite frequently as we keep updating different types of extensions. Every time we build a new custom Repository image with new versions of our extensions, and then start a container based on it, we will see that the Alfresco Data we had when testing the previous image is gone. This scenario may be sufficient for some developer scenarios. However, when you start this new container with a fresh content repository the database and search services will still have metadata and an index that matches when the previous content was added. To solve this you need to remove and restart the database and search services containers too.

 

We can get around this problem by connecting a Docker Volume to the Repository Container. The volume would then persists the Alfresco Data (alf_data) outside of the container life cycle.

Types of Docker Volumes

There are many different types of Docker Volumes with different characteristics. We need to choose one that fits our needs:

 

  • Host: A host volume lives on the Docker host's filesystem and can be accessed from within the container. To create a host volume do:
    • docker run -v /path/on/host:/path/in/container ...
  • Anonymous: An anonymous volume is useful for when you would rather have Docker handle where the files are stored. It can be difficult, however, to refer to the same volume over time when it is an anonymous volumes. To create an anonymous volume:
    • docker run -v /path/in/container …
    • Or in a Dockerfile: VOLUME /path/in/container
  • Named: A named volume is similar to an anonymous volume. Docker manages where on disk the volume is created, but you give it a name. To create a named volume use the following commands:
    • docker volume create somevolumename
    • docker run -v somevolumename:/path/in/container ...

 

The type of volume we will use is the Named. We will not use anonymous because it is difficult to find the volume associated with the data we are storing as the volume ID would look something like 08a2eb76f59faebe30ea972a683914f6011f4fe7fd0468152bfd4ff918f6709b. And an anonymous volume created from a Dockerfile would also not be useful as a new anonymous volume would be created every time we create a new container instance. A hosted volume would be very coupled to the operating system we use.

Creating a Named Repo Data Volume  

A named data volume would live its own life completely outside of container instances lifecycles. We can create it as follows for the Repository Data (i.e. alf_data):

 

$ docker volume create alf-repo-data
alf-repo-data


List the available volumes:

 

$ docker volume ls
DRIVER              VOLUME NAME
local               08a2eb76f59faebe30ea972a683914f6011f4fe7fd0468152bfd4ff918f6709b
local               8f5df54fcf77f5f5f8c740218c8a755aa3b18f7fa880631bc1f59d49e7ecbd72
local               alf-repo-data
local               c4b516ba67c1f9bfef106093db054d9388bdf0316f00e8ee2d7e69fcb9e01ee0
local               cecaf0c49f5e2c9fce247ef9ba9b48704707e6674e40f44545dcdc8a0a1e5809
local               de9fde85ca1ae2d60b79dff7386b11e7c6a289eff24bda3aa0ce6e3a01fc05f0
local               e39dacf1af8f1cc0451b2345ac43b5ea471e52f90d99ce92399eb17125d4df37


It’s very easy to spot the named volumes in the listing.

You might see a few volumes here as the PostgreSQL container uses anonymous volumes. We can remove unused volumes as follows:

 

$ docker volume prune
WARNING! This will remove all volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
e39dacf1af8f1cc0451b2345ac43b5ea471e52f90d99ce92399eb17125d4df37
cecaf0c49f5e2c9fce247ef9ba9b48704707e6674e40f44545dcdc8a0a1e5809
8f5df54fcf77f5f5f8c740218c8a755aa3b18f7fa880631bc1f59d49e7ecbd72
de9fde85ca1ae2d60b79dff7386b11e7c6a289eff24bda3aa0ce6e3a01fc05f0
c4b516ba67c1f9bfef106093db054d9388bdf0316f00e8ee2d7e69fcb9e01ee0
alf-repo-data

Total reclaimed space: 112.7MB

Running the Alfresco Repository Container with a Volume

We can now restart the custom Repository container and have it use the named alf-repo-data volume. Before we continue stop and remove all the running containers:

 

$ docker container stop alf-postgres alf-search alf-repo alf-share

$ docker container rm alf-postgres alf-search alf-repo alf-share

 

Now let’s kick off the PostgreSQL and Alfresco Search Services containers so we have  them running when we start the Repository (we assume the Docker network alf-net still exists):

 

$ docker run --network alf-net --name alf-postgres -p 5432:5432 -e POSTGRES_USER=alfresco -e POSTGRES_PASSWORD=alfresco -e POSTGRES_DB=alfresco -d postgres:10.1  

95ba7abc8e62ca912cd8afa87bc4d6e3ac5756a0f3daf854587127fd7e5f31ce

$ docker run --network alf-net --name alf-search -p 8983:8983 -e SOLR_ALFRESCO_HOST=alf-repo -e SOLR_ALFRESCO_PORT=8080 -e SOLR_SOLR_HOST=alf-search -e SOLR_SOLR_PORT=8983 -e SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive -d alfresco/alfresco-search-services:1.1.1 

a9f19ec0e3cc5134db42791fd1247fd85532cf3737f55d9f5aff1bd7f361048c

And now start the repository container based on the my-acs-repo image:

$ docker run -v alf-repo-data:/usr/local/tomcat/alf_data--network alf-net --name alf-repo -p 8080:8080 -e JAVA_OPTS='-Ddb.driver=org.postgresql.Driver -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.url=jdbc:postgresql://alf-postgres:5432/alfresco -Dsolr.host=alf-search -Dsolr.port=8983 -Dsolr.secureComms=none -Dsolr.base.url=/solr -Dindex.subsystem.name=solr6' -d my-acs-repo:6.0

2c601b2e8ec9bf06df877e21e9d60d9e3f9bf67b77c802ae574394ed0571c285

Note here how we attach the container to the alf-repo-data volume and map it to the container directory /usr/local/tomcat/alf-data. As soon as the container is started up all the content under /usr/local/tomcat/alf-data will be copied to the volume.

Review the logs and make sure the Repository container starts successfully:

 

$ docker container logs 2c601b2e8ec9bf06df877e21e9d60d9e3f9bf67b77c802ae574394ed0571c285

11-Apr-2018 12:07:13.058 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]

11-Apr-2018 12:07:13.093 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]

11-Apr-2018 12:07:13.104 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 64455 ms

Inspecting the Repository Data Volume

To see which volume is used by the alf-repo container we can list the volumes (mounts) associated with a container:

 

$ docker container inspect -f "{{ .Mounts }}" alf-repo

[

{

volume alf-repo-data /var/lib/docker/volumes/alf-repo-data/_data /usr/local/tomcat/alf_data

local

z

true

}

]

 

As expected the alf-repo container is associated with the alf-repo-data volume.

 

If we were on a Linux box, such as Ubuntu, we could just list the contents of the /var/lib/docker/volumes/alf-repo-data/_data directory. But on a Mac or Windows machine that does not work as Docker runs inside a Virtual Machine (VM).

 

To see persistent volumes created by Docker for Mac (or Docker for Windows) you need to login to that hidden VM first.

 

To do this, we need to use a serial terminal on a Mac. There's a terminal application called "screen" that we can use:

  1. Open a new terminal window
  2. Use the screen tool to get into the Docker driver by executing command: screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty
  3. You should see a blank screen, just press Enter, and after a while, you should see a command line prompt
  4. Now you're inside Docker's VM and you can cd into the volumes dir by typing: cd /var/lib/docker/volumes/alf-repo-data/_data

Add some content and then re-build the image

Let’s now try and see if we can re-build the custom Alfresco Repository image and still retain the content we have created so far.

Start a Share container and Add some content

Before we rebuild the Repo image we first need to add some content that we can verify with. Start the Alfresco Share container so we can add content:

 

$ docker run --network alf-net --name alf-share -p 8081:8080 -e REPO_HOST=alf-repo -e REPO_PORT=8080 -d alfresco/alfresco-share:6.0.a

160fe60f064515648acbd71fb82b69ec24de33841124943c17b0708ae049acf8

Login to Share and add a folder and file under Guest Home (use admin/admin when login):

Update and Build the Repo Extension

We will now make a small change to the custom-repo-extension/src/main/java/com/acme/alfresco/action/CustomRepoAction.java file to simulate that we have developed a new version of our Repo extension:

 

public class CustomRepoAction extends ActionExecuterAbstractBase {
private static final Logger LOG = LoggerFactory.getLogger(CustomRepoAction.class);

@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList) {
// No parameters are passed to action
}

@Override
protected void executeImpl(Action action, NodeRef actionedUponNodeRef) {
System.out.println("Now, do something ... UPDATED");
}
}

 

In this case I just updated the println statement.

 

Now build the project to create a new extension version:

 

custom-repo-extension mbergljung$ mvn clean install

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building Custom repository extension JAR 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

....

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/custom-repo-extension/pom.xml to /Users/mbergljung/.m2/repository/org/alfresco/training/custom-repo-extension/1.0-SNAPSHOT/custom-repo-extension-1.0-SNAPSHOT.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 3.463 s

[INFO] Finished at: 2018-04-12T08:29:30+01:00

[INFO] Final Memory: 42M/324M

[INFO] ------------------------------------------------------------------------

Rebuild the Repo image and restart Repo container

With the new extension version ready we can rebuild the Repo Image:

 

docker-alfresco-custom mbergljung$ docker build .  --tag my-acs-repo:6.1

Sending build context to Docker daemon  44.03kB

Step 1/6 : FROM alfresco/alfresco-content-repository-community:6.0.4-ea

---> df0b08d0d3a3

Step 2/6 : ARG TOMCAT_DIR=/usr/local/tomcat

---> Using cache

---> 1b0322f285fb

Step 3/6 : RUN mkdir -p $TOMCAT_DIR/amps

---> Using cache

---> 393c1f52691f

Step 4/6 : COPY target/amps $TOMCAT_DIR/amps

---> Using cache

---> 56260db9a225

Step 5/6 : COPY target/jars $TOMCAT_DIR/webapps/alfresco/WEB-INF/lib

---> Using cache

---> 09f8f701f2a2

Step 6/6 : RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install               $TOMCAT_DIR/amps $TOMCAT_DIR/webapps/alfresco -directory -nobackup -force

---> Using cache

---> fd4bb88fe25d

Successfully built fd4bb88fe25d

Successfully tagged my-acs-repo:6.1

We give the new image the name my-acs-repo, which is the same name as we used before. But we use version 6.1 to denote a newer build with newer versions of the extensions (we could remove version 6.0 of the image and use the same version number if we wanted to).

Now list the images to verify that we got version 6.1:

 

docker-alfresco-custom mbergljung$ docker image ls

REPOSITORY                                       TAG IMAGE ID CREATED           SIZE

my-acs-repo                                      6.1 fd4bb88fe25d 26 hours ago        1.74GB

my-acs-repo                                      6.0 8816690d43e7 2 days ago          1.72GB

my-acs-share                                     6.0 e760d22a715a 6 days ago          709MB

...

With the new 6.1 image available we can stop, remove, and restart the Repo container:

$ docker container stop alf-repo

alf-repo

$ docker container rm alf-repo

alf-repo

 

Make sure the named volume is still there:

$ docker volume ls

DRIVER              VOLUME NAME

local               08a2eb76f59faebe30ea972a683914f6011f4fe7fd0468152bfd4ff918f6709b

local               alf-repo-data

...

Start the repository container based on version 6.1 of the my-acs-repo image:

$ docker run -v alf-repo-data:/usr/local/tomcat/alf_data--network alf-net --name alf-repo -p 8080:8080 -e JAVA_OPTS='-Ddb.driver=org.postgresql.Driver -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.url=jdbc:postgresql://alf-postgres:5432/alfresco -Dsolr.host=alf-search -Dsolr.port=8983 -Dsolr.secureComms=none -Dsolr.base.url=/solr -Dindex.subsystem.name=solr6' -d my-acs-repo:6.1

1c5b74efa499f3624ece7b995bddc81e53548b3b4047bf238156c2b693cce471

 

Review the logs and make sure it is up and running.

Make sure content is intact

And now to the fun part. Login to Share, if needed, and make sure the folder and file previously uploaded is still there. They are kept in the external named volume, which should be independent of container life cycle.

Building and Running an Alfresco Repo Image with MySQL

Event though this article focuses a lot on the development environment you might still want to run it with a different database than the out-of-the-box PostgreSQL alternative. Maybe you like MySQL more, or have more experience with it.

 

In this section we will have a look at how to run a MySQL container instead of the PostgreSQL container. We will also have to figure out how to install the MySQL Connector JDBC driver into the Repository container.

Running a MySQL container with the Alfresco Database

The Alfresco Repo is going to connect to a MySQL database called ‘alfresco’ where the Repository can store the metadata for the content files. We can easily fire up a MySQL database with images available at https://hub.docker.com/_/mysql/.

 

We can look at the Docker Hub page for MySQL to see what environment variables we need to use to configure the database image. Kick off a new MySQL container as follows and give the new container the name alf-mysql (we assume that the alf-net network still exists):

 

$ docker run --network alf-net --name alf-mysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_DATABASE=alfresco -e MYSQL_USER=alfresco -e MYSQL_PASSWORD=alfresco -d mysql:5.7.17 --character-set-server=utf8 --collation-server=utf8_general_ci --max_connections=1024

7921db488804459ebfa84dd6f5ff89d33bd4412f0fa690d4dda38f88394f6b50

 

The --networkoption must be specified directly after run. It cannot, for example, be at the end of the command.

 

Here we start a MySQL container with user/pwd alfresco/alfresco and configure it to create the default database with the name alfresco, which is what the repository needs. The database server is available externally on port 3306. We also connect the container to the alf-net network we created earlier on. The command returns the new container’s ID.

 

Test that it all worked by logging into the container and accessing the database (note that we use the short ID for the container):

 

$ docker container ls

CONTAINER ID        IMAGE COMMAND                  CREATED STATUS PORTS                    NAMES

7921db488804        mysql:5.7.17 "docker-entrypoint.s…"   19 seconds ago Up 20 seconds 0.0.0.0:3306->3306/tcp   alf-mysql

 

$ docker container exec -it 7921db488804/bin/bash

root@7921db488804:/# mysql -u alfresco -p

Enter password:

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 3

Server version: 5.7.17 MySQL Community Server (GPL)

 

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

 

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

 

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

 

mysql> show tables;

Empty set (0.00 sec)

 

mysql> exit;

Bye

root@7921db488804:/# exit

exit

Building and Running an Alfresco Repo Container connecting to MySQL

The Alfresco database is now ready in the MySQL container. We need to build a Repository image containing the mysql-connector-java-5.1.42.jar JDBC driver.

Create and run a POM file that brings in the MySQL connector

First we will create a Maven POM that defines a dependency to the MySQL Connector and then copies it into the target/libs directory when we run the build. This POM is part of the acs-community-packaging-custom project that you downloaded earlier on. If you look into the docker-alfresco-custom-mysql sub-project you will find the POM file, which looks like this:

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.alfresco.training</groupId>
<artifactId>docker-alfresco-custom-mysql</artifactId>
<version>1.0-SNAPSHOT</version>
<name>LIB assembly under /target for use by Dockerfile</name>
<packaging>pom</packaging>

<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-libs</id>
<phase>process-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.42</version>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

 

This POM file defines a dependency to the correct version (i.e. the supported one) of the MySQL JDBC connector and then we use the maven-dependency-plugin to copy the jar into the target/libs directory, where it will be ready to be picked up by the Dockerfile.

 

Now run the build:

 

docker-alfresco-custom-mysql mbergljung$ mvn clean install

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building LIB assembly under /target for use by Dockerfile 1.0-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ docker-alfresco-custom-mysql ---

[INFO] Deleting /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-alfresco-custom-mysql/target

[INFO]

[INFO] --- maven-dependency-plugin:3.0.2:copy (copy-libs) @ docker-alfresco-custom-mysql ---

[INFO] Configured Artifact: mysql:mysql-connector-java:5.1.42:jar

[INFO] Copying mysql-connector-java-5.1.42.jar to /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-alfresco-custom-mysql/target/libs/mysql-connector-java-5.1.42.jar

[INFO]

[INFO] --- maven-install-plugin:2.4:install (default-install) @ docker-alfresco-custom-mysql ---

[INFO] Installing /Users/mbergljung/DeployProjects/acs-community-packaging-custom/docker-alfresco-custom-mysql/pom.xml to /Users/mbergljung/.m2/repository/org/alfresco/training/docker-alfresco-custom-mysql/1.0-SNAPSHOT/docker-alfresco-custom-mysql-1.0-SNAPSHOT.pom

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESS

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 0.916 s

[INFO] Finished at: 2018-04-10T15:14:22+01:00

[INFO] Final Memory: 12M/309M

[INFO] ------------------------------------------------------------------------

Looking in the target/libs directory we should now see the following:

docker-alfresco-custom-mysql mbergljung$ tree

.

├── Dockerfile

├── pom.xml

└── target

   └── libs

       └── mysql-connector-java-5.1.42.jar

Create and build a Dockerfile that injects the MySQL Connector

We are now ready to create the Dockerfile that injects the MySQL JDBC driver into the Repository image. The Dockerfile looks as follows and is also located in the docker-alfresco-custom-mysql directory:

 

FROM alfresco/alfresco-content-repository-community:6.0.5-ea

ARG TOMCAT_LIB_DIR=/usr/local/tomcat/lib

COPY target/libs $TOMCAT_LIB_DIR

 

The file is very simple, it just takes the standard Repository image as a starting point and then copies the JDBC driver into it. Building the image looks like this:

 

docker-alfresco-custom-mysql mbergljung$ docker build . --tag my-acs-repo-mysql:6.0

Sending build context to Docker daemon  1.004MB

Step 1/3 : FROM alfresco/alfresco-content-repository-community:6.0.5-ea

---> df0b08d0d3a3

Step 2/3 : ARG TOMCAT_LIB_DIR=/usr/local/tomcat/lib

---> Using cache

---> e14ed38cfbe5

Step 3/3 : COPY target/libs $TOMCAT_LIB_DIR

---> Using cache

---> 8816690d43e7

Successfully built 8816690d43e7

Successfully tagged my-acs-repo-mysql:6.0

We give the new image the name my-acs-repo-mysql and version 6.0. List the images so we see that it worked:

$ docker image ls

REPOSITORY                                       TAG IMAGE ID CREATED            SIZE

my-acs-repo-mysql                                6.0 8816690d43e7 About a minute ago   1.72GB

my-acs-repo                                      6.0 8816690d43e7 About a minute ago   1.72GB

...

Run the Alfresco Repository Container with MySQL

We are now ready to kick off the custom Repository container with the MySQL JDBC driver and connect to the MySQL container. But let’s first kick off the Alfresco Search Services container so we have that running when the repo starts up:

 

$ docker run --network alf-net --name alf-search -p 8983:8983 -e SOLR_ALFRESCO_HOST=alf-repo -e SOLR_ALFRESCO_PORT=8080 -e SOLR_SOLR_HOST=alf-search -e SOLR_SOLR_PORT=8983 -e SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive -d alfresco/alfresco-search-services:1.1.1 

0b4ca7a949adb2d8b2f07cb1d5ec95a51b350c54c762a577b3f275742d1b95d1

And now the repository container based on the my-acs-repo-mysql image:

$ docker run --network alf-net --name alf-repo -p 8080:8080 -e JAVA_OPTS='-Ddb.driver=org.gjt.mm.mysql.Driver -Ddb.username=alfresco -Ddb.password=alfresco -Ddb.url="jdbc:mysql://alf-mysql:3306/alfresco?useUnicode=yes&characterEncoding=UTF-8" -Dsolr.host=alf-search -Dsolr.port=8983 -Dsolr.secureComms=none -Dsolr.base.url=/solr -Dindex.subsystem.name=solr6' -d my-acs-repo-mysql:6.0

cdad9c60dd0e46bad24c7e5ff96a2c76b964616905e5effa2664a6b51e8c1af3

Review the logs and make sure it connects to MySQL successfully:

$ docker container logs cdad9c60dd0e46bad24c7e5ff96a2c76b964616905e5effa2664a6b51e8c1af3

10-Apr-2018 15:30:06.292 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:        Apache Tomcat/8.5.28

.

org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Ddb.driver=org.gjt.mm.mysql.Driver

10-Apr-2018 15:30:06.298 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Ddb.username=alfresco

10-Apr-2018 15:30:06.298 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Ddb.password=alfresco

10-Apr-2018 15:30:06.298 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Ddb.url=jdbc:mysql://alf-mysql:3306/alfresco?useUnicode=yes&characterEncoding=UTF-8

...

2018-04-10 15:30:28,393  INFO [alfresco.repo.admin] [localhost-startStop-1] Using database URL 'jdbc:mysql://alf-mysql:3306/alfresco?useUnicode=yes&characterEncoding=UTF-8' with user 'alfresco'.

2018-04-10 15:30:28,394  INFO [alfresco.repo.admin] [localhost-startStop-1] Connected to database MySQL version 5.7.17

...

2018-04-10 15:30:42,972  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Connecting to database: jdbc:mysql://alf-mysql:3306/alfresco?useUnicode=yes&characterEncoding=UTF-8, UserName=alfresco@172.21.0.4, MySQL Connector Java

2018-04-10 15:30:42,972  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Schema managed by database dialect org.alfresco.repo.domain.dialect.MySQLInnoDBDialect.

2018-04-10 15:30:43,118  WARN [domain.schema.SchemaBootstrap] [localhost-startStop-1] Schema validation found 46 potential problems, results written to: /usr/local/tomcat/temp/Alfresco/Alfresco-MySQLInnoDBDialect-Validation-Pre-Upgrade-alf_-1005770665855180801.txt

2018-04-10 15:30:43,133  WARN [domain.schema.SchemaBootstrap] [localhost-startStop-1] Schema validation found 25 potential problems, results written to: /usr/local/tomcat/temp/Alfresco/Alfresco-MySQLInnoDBDialect-Validation-Pre-Upgrade-act_-2723159380226551365.txt

2018-04-10 15:30:43,214  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Normalized schema dumped to file /usr/local/tomcat/temp/Alfresco/Alfresco-schema-MySQLInnoDBDialect-pre-upgrade-alf_-7824608645271764904.xml.

2018-04-10 15:30:43,214  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Normalized schema dumped to file /usr/local/tomcat/temp/Alfresco/Alfresco-schema-MySQLInnoDBDialect-pre-upgrade-act_-1758568877658060149.xml.

2018-04-10 15:30:43,278  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-4701688511608734693.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-RepoTables.sql).

2018-04-10 15:30:43,728  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-1660864257659333372.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-LockTables.sql).

2018-04-10 15:30:43,765  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-8147065905659118747.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-ContentTables.sql).

2018-04-10 15:30:43,843  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-2319822585342629214.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-PropertyValueTables.sql).

2018-04-10 15:30:43,982  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-7958840531865558083.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-ContentUrlEncryptionTables.sql).

2018-04-10 15:30:44,014  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-1493698802374057751.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-AuditTables.sql).

2018-04-10 15:30:44,071  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-3935710904755261199.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-ActivityTables.sql).

2018-04-10 15:30:44,121  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-2654492923882306612.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-UsageTables.sql).

2018-04-10 15:30:44,147  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-481654729795371565.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-SubscriptionTables.sql).

2018-04-10 15:30:44,162  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-7428379169648063519.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-TenantTables.sql).

2018-04-10 15:30:44,184  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Executing database script /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-Update-4157934858382764547.sql (Copied from classpath:alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/AlfrescoCreate-AuthorizationTables.sql).

2018-04-10 15:30:44,215  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Create scripts executed in 1209 ms

2018-04-10 15:30:46,029  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] All executed statements:  /usr/local/tomcat/temp/Alfresco/AlfrescoSchema-MySQLInnoDBDialect-All_Statements-638494183242731673.sql.

2018-04-10 15:30:46,317  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Compared database schema with reference schema (all OK): class path resource [alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/Schema-Reference-ALF.xml]

2018-04-10 15:30:46,507  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Compared database schema with reference schema (all OK): class path resource [alfresco/dbscripts/create/org.alfresco.repo.domain.dialect.MySQLInnoDBDialect/Schema-Reference-ACT.xml]

2018-04-10 15:30:46,870  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Normalized schema dumped to file /usr/local/tomcat/temp/Alfresco/Alfresco-schema-MySQLInnoDBDialect-post-upgrade-alf_-1249302916559560216.xml.

2018-04-10 15:30:46,870  INFO [domain.schema.SchemaBootstrap] [localhost-startStop-1] Normalized schema dumped to file /usr/local/tomcat/temp/Alfresco/Alfresco-schema-MySQLInnoDBDialect-post-upgrade-act_-1757141603492957245.xml.

[localhost-startStop-1] Alfresco Content Services started (Community Early Access). Current version: 6.0.4 (re493fa84-b38) schema 10,201. Originally installed version: 6.0.4 (re493fa84-b38) schema 10,201.

...

Check access via WebDAV

Verify that the Repository container is up and running successfully with the MySQL database. Connect to WebDAV via http://localhost:8080/alfresco/webdav.

Filter Blog

By date: By tag: