Friday, July 24, 2020

Change ACS 6.x/7.x, Share 6.x/7.x, Proxy (nginx), Solr6 and DB (postgres) ports using docker-compose.yml and DockerFile


It is a very common requirement to use different set of available port (s) as per company policy rather than using default port (s) for the applications.


Background:


Before container based environments, we had to follow below given steps in order to change the ports (these points still applies to an environment setup via distribution package):

    • Update default connector ports 8080, 8443, 8009 and 8005 to required ports.
    • Sometimes we use JPDA_ADDRESS for remote debug which is default '8000' in $ALFRESCO_INSTALL_DIR/tomcat/bin/catalina.sh. If we use remote debug, them update to required port as needed.
  • Update the required 'alfresco' and 'share' ports in $ALFRESCO_INSTALL_DIR/tomcat/shared/classes/alfresco-global.properties
  • Update the required 'alfresco' ports in $ALFRESCO_INSTALL_DIR/tomcat/shared/classes/alfresco/web-extension/share-config-custom.xml for remote configuration (<config evaluator="string-compare" condition="Remote">).
        • http://localhost:{REQUIRED_PORT}/alfresco/s --> DEFAULT: 8080
      • Update 'alfresco' endpoint url: 
        • http://localhost:{REQUIRED_PORT}/alfresco/s --> DEFAULT: 8080
      • Update 'alfresco-feed' endpoint url: 
        • http://localhost:{REQUIRED_PORT}/alfresco/s --> DEFAULT: 8080
      • Update 'alfresco-api' endpoint url: 
        • http://localhost:{REQUIRED_PORT}/alfresco/api --> DEFAULT: 8080
  • Update the required 'alfresco' port in 'solrcore.properties' file.
    • Find the 'alfresco.port' property in solrcore.properties file and update:
      • alfresco.port=<requiredPort>, default : 8080
    • For SOLR4, we used below paths:
      • $ALFRESCO_INSTALL_DIR/solr4/workspace-SpacesStore/conf/solrcore.properties
      • $ALFRESCO_INSTALL_DIR/solr4/archive-SpacesStore/conf/solrcore.properties
      • $SOLR_HOME/solrhome/alfresco/conf/solrcore.properties
      • $SOLR_HOME/solrhome/archive/conf/solrcore.properties



All the above given steps will be almost same for ACS 6.x as well if you are using standalone installation and not managing the services, images and containers via docker based deployment. 

When using docker based deployment, we use docker-compose.yml file to configure all the services which will be used as a base for launching the corresponding containers. We configure all the required ports (host and container ports) in the docker-compose.yml file and expose any ports if required either via docker-compose.yml or DockerFile.

It is possible to change the host ports via docker-compose.yml file but default ports (container ports) which are exposed within docker images (specially connector ports in tomcat which is shipped with acs and share images) can't be changed via docker-compose.yml alone. We have to take help of DockerFile, which can be used to update required ports at the time of build process.

Similarly, if you are using proxy (nginx) then 'ngnix.conf' configuration also needs an update to reference the required ports. By default ngnix will try to forward all requests to '8080' which is default port for acs and share.

It will be like re-builing the original images (acs, share, proxy etc. images) with updated ports and containers will be launced using the updated images. 

For some of the servives such as 'postgres', you can change the default port directly from docker-compose.yml as it gets access to command line, it is like executing 'postgres -p 5433' via command line. 
We can simply pass the command line param '-p <requiredPort>' or use 'expose' option in docker-compose.yml in the 'postgres' service definition.

For 'solr6 (alfresco-search-service)', we can either update the startup script or update the shared.properties via DockerFile or add SOLR_PORT environment variable in docker-compose.yml. This env variable will be used by jetty server to start service on required port. 
Additionally, you can also pass Jvm param using JAVA_OPTS, e.g. -Djetty.port=9999

Change Alfresco, Share, Nginx (Proxy), Solr and Database (postgres) ports with help of DockerFile and docker-compose.yml:


Considering the aforementioned steps for changing the ports, we need to follow the same  approach for docker based deployment as well but with help of docker-compose.yml and DockerFile.

I will be using port '7080' instead of '8080' for acs, share and proxy. I will also update the tomcat connector ports to 7005, 7009 and 7443. I will use '5555' instead of '5432' for postgres and '9999' instead of '8983' for solr6.


Here are default ports:

Service

Default Ports

Note

Tomcat connector ports

8005, 8080, 8443, 8009

Default within tomcat shipped with alfresco and share images.

alfresco

8080

 

share

8080

 

proxy

80, 8080 -> 8080

Default port on proxy(nginx) is 80, where port 8080 is exposed for providing access to alfresco and share. nginx forwards requests on 8080 (host port) to alfresco’s and share’s port 8080.

We can change the host port to any other port as well easily. E.g. 81 -> 8080 (Request will come on port 81 which nginx will forward to 8080)

postgres

5432

 

solr6

8083 -> 8983

8083 is host port and 8983 is container port. Alfresco uses 8983 to communicate with solr6. To access solr admin, administrators use 8083

 

Access via browser: http://localhost:8083/

 

transform-core-aio

8090-> 8090

Both host and container ports are same here.

Alfresco uses 8090 to communicate with transformation services.

We can use the port 8090 to access the transformation services via browser.

 

Access via browser: http://localhost:8090/

 

activemq

8161 -> 8161 # Web Console

Both host and container ports are same here.

port 8161 can be used for accessing the ‘Web Console’ via browser and alfresco would use the same port to communicate with activemq.

 

Access WebConsole via browser: http://localhost:8161/

 


The steps we are going to follow, are applicable to ACS 6.x , ACS7.1 and ACS 7.2

This post has been updated to match the latest ACS version (ACS 7.3) as well. 

Let's create some directories for keeping the DockerFile and required configs which will be used for re-building the updated images from OOTB images.

  • Create a directory 'configs-to-override' in the same directory where you have kept your 'docker-compose.yml' file.
  • Under 'configs-to-override' directory, create following directories:
    • Create 'alfresco' directory --> It will be used to keep 'DockerFile' for acs image
      • Create an empty 'DockerFile' file which we will use to put build instructions for 'alfresco' service
    • Create 'share' directory --> It will be used to keep 'DockerFile' for share image
      • Create an empty 'DockerFile' file which we will use to put build instructions for 'share' service
    • Create 'proxy' directory --> It will be used to keep 'DockerFile' and 'nginx.conf' file for nginx image
      • Create an empty 'DockerFile' file which we will use to put build instructions for 'proxy' service
      • Create an empty 'nginx.conf' file which we will use to put proxy configuration for services

  • Update the required ports in /usr/local/tomcat/tomcat/conf/server.xml via DockerFile
    • Open the 'DockerFile' created under 'configs-to-override/alfresco'
    • Add the following instructions: 

FROM alfresco/alfresco-content-repository-community:7.3.0

ARG TOMCAT_SERVER_PORT=7005
ARG TOMCAT_HTTP_PORT=7080
ARG TOMCAT_SSL_PORT=7443
ARG TOMCAT_AJP_PORT=7009

ARG TOMCAT_DIR=/usr/local/tomcat

#Change to root so that sed command can be executed
USER root

#Update port to 7080 from 8080, 7005 from 8005, 7443 from 8443, 7009 from 8009
RUN sed -i "s/<Server\ port=\"8005\"\ shutdown=\"SHUTDOWN\">/<Server\ port=\"$TOMCAT_SERVER_PORT\"\ shutdown=\"SHUTDOWN\">/g" $TOMCAT_DIR/conf/server.xml ; \
    sed -i "s/port=\"8080\"\ protocol=\"HTTP\/1.1\"/port=\"$TOMCAT_HTTP_PORT\"\ protocol=\"HTTP\/1.1\"/g" $TOMCAT_DIR/conf/server.xml ; \
	sed -i "s/\ <Connector\ port=\"8443\"/\ <Connector port=\"$TOMCAT_SSL_PORT\"/g" $TOMCAT_DIR/conf/server.xml ; \
	sed -i "s/\ <Connector\ port=\"8009\"\ protocol=\"AJP\/1.3\"/\  <Connector\ port=\"$TOMCAT_AJP_PORT\"\ protocol=\"AJP\/1.3\"\ /g" $TOMCAT_DIR/conf/server.xml ; \
	sed -i "s/redirectPort=\"8443\"/redirectPort=\"$TOMCAT_SSL_PORT\"/g" $TOMCAT_DIR/conf/server.xml ;

#Change back to alfresco
USER alfresco

#TODO:: Add more steps as needed

    • Open the 'DockerFile' created under 'configs-to-override/share'
    • Add the following instructions: 

FROM alfresco/alfresco-share:7.3.0

ARG TOMCAT_SERVER_PORT=7005
ARG TOMCAT_HTTP_PORT=7080
ARG TOMCAT_SSL_PORT=7443
ARG TOMCAT_AJP_PORT=7009

ARG TOMCAT_DIR=/usr/local/tomcat

#Update port to 7080 from 8080, 7005 from 8005, 7443 from 8443, 7009 from 8009
RUN sed -i "s/<Server\ port=\"8005\"\ shutdown=\"SHUTDOWN\">/<Server\ port=\"$TOMCAT_SERVER_PORT\"\ shutdown=\"SHUTDOWN\">/g" $TOMCAT_DIR/conf/server.xml ; \ sed -i "s/port=\"8080\"\ protocol=\"HTTP\/1.1\"/port=\"$TOMCAT_HTTP_PORT\"\ protocol=\"HTTP\/1.1\"/g" $TOMCAT_DIR/conf/server.xml ; \ sed -i "s/\ <Connector\ port=\"8443\"/\ <Connector port=\"$TOMCAT_SSL_PORT\"/g" $TOMCAT_DIR/conf/server.xml ; \ sed -i "s/\ <Connector\ port=\"8009\"\ protocol=\"AJP\/1.3\"/\ <Connector\ port=\"$TOMCAT_AJP_PORT\"\ protocol=\"AJP\/1.3\"\ /g" $TOMCAT_DIR/conf/server.xml ; \ sed -i "s/redirectPort=\"8443\"/redirectPort=\"$TOMCAT_SSL_PORT\"/g" $TOMCAT_DIR/conf/server.xml ;
#TODO:: Add more steps as needed

  • Update the 'alfresco' service definition with following config and remove image config (used for pulling docker image for alfresco). Image config will go to DockerFile. See DockerFile instructions above for alfresco.
            

 build:

    dockerfile: ./Dockerfile

    context: ./configs-to-override/alfresco



      • share.port=7080
      • alfresco.port=7080
      • solr.port=9999
      • db.url=jdbc:postgresql://postgres:5555/alfresco
      • aos.baseUrlOverwrite=http://localhost:7080/alfresco/aos
This sets the alfresco and share ports via jmx. So no need to update anything in alfresco-global.properties file. However, if you would like to use 'alfresco-global.properties' then you have to either open and append properties in '/usr/local/tomcat/tomcat/shared/classes/alfresco-global.properties' file via DockerFile or Copy/Replace 'alfresco-global.properties' via DockerFile. And remove jmx params from JAVA_OPTS for the ports.

 

  • Update the 'share' service definition with following config and remove image config (used for pulling docker image for share). Image config will go to DockerFile. See DockerFile instructions above for share.

 build:

     dockerfile: ./Dockerfile

    context: ./configs-to-override/share


  • Update the required 'alfresco' port in 'share' service definition under JAVA_OPTS
      • alfresco.port=7080
  • Update following REPO_PORT env variable in 'share' service definition:
      • REPO_PORT: "7080"
             This is sufficient to update ports for endpoint-urls in 'share-config-custom.xml'

                    #Solr needs to know how to register itself with Alfresco
      • SOLR_ALFRESCO_PORT=7080 
                    #Alfresco needs to know how to call solr
      • SOLR_SOLR_PORT=9999 
    This is sufficient to update ports for solr6 (alfresco-search-service) solrcore.properties,  'SOLR_ALFRESCO_PORT' and 'SOLR_SOLR_PORT' is externalized configuration and considered best practice to use instead of updating the 'solrcore.properties' file directly. 
    For any property, only the environment variables should be specified in the /opt/alfresco-search-services/solr.in.sh/ OR /opt/alfresco-search-services/solr.in.cmd file. For example, SOLR_SOLR_HOST, SOLR_SOLR_PORT, or SOLR_ALFRESCO_PORT. Besides the solr.in.sh/solr.in.cmd file, you can also set these properties in the /opt/alfresco-search-services/solrhome/conf/shared.properties file.
     
    • Add following SOLR_PORT env variable in 'solr6' service definition:
                #Solr jetty port, to start solr6 on port 9999
      • SOLR_PORT=9999
     

    ports:
       - 8083:9999 #Browser port
    


    • Update 'ports' configuration in 'postgres' service definition and update 'environment' variable named PGPORT:

     environment:
       - PGPORT=5555 
     ports:
       - 5555:5555
    

    • At last, Update the 'nginx.conf' file which we created initially, update the DockerFile and update the 'ports' configuration in 'proxy' service definition:
      • Open the 'DockerFile' created under 'configs-to-override/proxy'
      • Add the following instructions:

    FROM alfresco/alfresco-acs-nginx:3.4.2
    
    # You can pass additional urls via environment variables. It doesn't seem to be working for me at the moment. See: https://github.com/Alfresco/acs-ingress/blob/master/entrypoint.sh
    
    # Replace all 8080 ports to 7080. Not a good way to do but short term option.
    RUN sed -i "s|\:8080|\:7080 |g" /etc/nginx/nginx.conf;
    RUN sed -i "s|\:8080|\:7080 |g" entrypoint.sh;

      • Update the 'proxy' service definition with following config and remove image config (used for pulling docker image for alfresco-nginx). Image config will go to DockerFile. See DockerFile instructions above for nginx.

     build:

         dockerfile: ./Dockerfile

        context: ./configs-to-override/proxy


      • Update 'ports' configuration and memory_limit in 'proxy' service definition:

    ports:
     - 7080:7080
    

    mem_limit: 256m


    After updates, use docker-compose -f ./docker-compose.yml up --build command to build and launch the updated containers.

    Refer this demo project which includes all the aforementioned steps. 


    For testing port changes, you can also check out the above given project and simply use "launcher.bat/launcher.sh" script to start the containers. Follow the instructions given here

    ----------------------------------------------------------------------------------------------------------
    For some useful docker and docker compose commands visit: 



    To know more on docker-compose CLI



    To know more on DockerFile, refer:  



    To know more on docker-compose.yml, refer: 



    Build and run your own image: 




    7 comments:

    1. Thank you for the article. I am trying to configure SSL and access by 443 port in alfresco docker 6.2, could you help me?

      ReplyDelete
    2. I will do SSL based setup soon. Till the you can refer these posts/docs, may be helpful for your use case.

      https://docs.alfresco.com/search-community/tasks/solr-install.html
      https://hub.alfresco.com/t5/alfresco-content-services-blog/alfresco-6-1-is-coming-with-mutual-tls-authentication-by-default/ba-p/287905
      https://github.com/Alfresco/alfresco-ssl-generator
      https://hub.alfresco.com/t5/alfresco-content-services-blog/alfresco-mtls-configuration-deep-dive/ba-p/296422
      https://github.com/aborroy/alfresco-solr-docker-mtls
      https://www2.slideshare.net/angelborroy/alfresco-certificates

      ReplyDelete
    3. Thanks for this awesome tutorial, i did setup everything based on your repository and everything starts fine. But when i try to load solr admin console, i get an error: Authentication failure: “secret” method has been selected. Use the right request header.

      I am not sure how to solve this error, any clues?

      ReplyDelete
      Replies
      1. Thanks, glad to hear. One of the major changes that has been done since ACS7.2 and ASS 2.x is that, solr.secureComms=none is no longer supported. Only "secret" or "https" are supported. "secret" mode is now default mode and that's why you see the message. In order to launch the solr admin, you need to pass a header "X-Alfresco-Search-Secret" with value "secretpassword" as configured here: https://github.com/abhinavmishra14/change-acs-share-port-demo/blob/master/docker-compose.yml#L40

        Delete
      2. Thank you sir, it worked.

        PS: I love you

        Delete
    4. Can we use Alfresco Identity Services with 23.1 community edition???

      ReplyDelete
    5. Yes you can, i would however recommend to use Out of the box Keycloak instead of AIS since it is being deprecated. Check here for more details: https://hub.alfresco.com/t5/alfresco-content-services-blog/alfresco-identity-service-end-of-life/ba-p/317195

      ReplyDelete

    Thanks for your comments/Suggestions.