Recently I’ve been tasked to set up Confluence server installation. One of my friends was in need and I decided it would be nice to play a bit with the whole setup.

As this is pro-bono and really not quite production install (meaning they use it, but it is not so downtime critical) there was a place to experiment with it a bit thus I decided to run Confluence in a Docker. Atlassian has pre-built image for confluence available via atlassian/confluence-server so that meant I haven’t had to compile image myself, which is most likely the best outcome since it should be easier to keep it up-to-date this way.

As the setup evolved, remembering commands used to run the container was becoming cumbersome, so I ended up defining it in docker-compose. So without further ado, here’s final version of my docker-compose.yml file:

version: '3'                                                                                                                          
services:
  db:
    image: postgres:11
    volumes:
      - /home/postgresql/confluence/data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=PASSWORD
      - POSTGRES_USER=confluence
    container_name: postgresql-confluence
    networks:
      - confluence
       
  confluence:
    image: atlassian/confluence-server
    volumes:
      -  /home/confluence/var/atlassian/application-data/confluence:/var/atlassian/application-data/confluence
    container_name: confluence
    ports:
      - "8090:8090"
      - "8091:8091"
    environment:
      - CATALINA_CONNECTOR_PROXYNAME="YOURINSTALLURL"
      - CATALINA_CONNECTOR_PROXYPORT=443
      - CATALINA_CONNECTOR_SCHEME=https
      - CATALINA_CONNECTOR_SECURE=true
    networks:
      - confluence
    depends_on:
      - db
 
networks:
  confluence:

The whole setup is behind the Nginx proxy which is used for SSL connection termination so we pass hostname and other variables in the compose file above. Reason to do it that way and not expose it directly or have another Nginx container is that there are also some other sites on that server which aren’t (and likely won’t be) containerized. So your setup may vary.

Full Nginx proxy setup is as follows:

server {                                                                                                                              
        listen 80;
        listen [::]:80;
        server_name YOURINSTALLURL;
 
        location /.well-known {
                root /var/www/well-known/;
        }
 
        # Enforce HTTPs
        return 301 https://$server_name$request_uri;
}
 
server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name YOURINSTALLURL;
 
        ssl_certificate /etc/letsencrypt/live/YOURINSTALLURL/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/YOURINSTALLURL/privkey.pem;
        include includes/ssl.conf;
 
        location /.well-known {
                root /var/www/well-known/;
        }
 
        location / {
                client_max_body_size 100m;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass https://localhost:8090;
                proxy_connect_timeout 300;
        }
 
        location /synchrony {
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass https://localhost:8091/synchrony;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_connect_timeout 300;
        }
 
        location /server-info.action {
                proxy_pass https://localhost:8090/server-info.action;
                proxy_connect_timeout 300;
        }
}