PROBLEM
Let’s assume we are going to run 3 containers:-
- Jenkins – http://server:8080/jenkins
- Nexus – http://server:8081/nexus
- Nginx – http://server
Nginx is used to serve cleaner URLs through reverse proxies so that users will access http://server/jenkins and http://server/nexus instead of remembering specific ports.
So, the simplified docker-compose.yml looks like this:-
version: '2'
services:
jenkins:
image: "jenkinsci/jenkins"
ports:
- "8080:8080"
volumes:
- jenkins:/var/jenkins_home
environment:
JENKINS_OPTS: "--prefix=/jenkins"
nexus:
image: "sonatype/nexus3"
ports:
- "8081:8081"
volumes:
- nexus:/nexus-data
environment:
NEXUS_CONTEXT: "nexus"
nginx:
build: ./nginx
ports:
- "80:80"
links:
- jenkins
- nexus
volumes:
jenkins:
nexus:
While http://server/jenkins and http://server/nexus work flawlessly, the Jenkins container is unable to communicate with Nexus through http://server/nexus/some/path, which is handled by Nginx.
Hence, when a Jenkins job tries to pull artifacts from Nexus, the following error is thrown:
[ERROR] Unresolveable build extension: Plugin ... or one of its
dependencies could not be resolved: Failed to collect dependencies
at ... -> ...: Failed to read artifact descriptor for ...: Could
not transfer artifact ... from/to server
(http://server/nexus/repository/public/): Connect to server:80
[server/172.19.0.2] failed: Connection refused (Connection refused)
-> [Help 2]
SOLUTION: ATTEMPT #1
The first attempt is to set up a link between Jenkins and Nginx with the Nginx alias pointing to the hostname, which is server.
The goal is when Jenkins communicate with Nexus through http://server/nexus/some/path, Nginx will handle the reverse proxy accordingly.
version: '2'
services:
jenkins:
image: "jenkinsci/jenkins"
ports:
- "8080:8080"
volumes:
- jenkins:/var/jenkins_home
environment:
JENKINS_OPTS: "--prefix=/jenkins"
links:
- nginx:${HOSTNAME}
nexus:
image: "sonatype/nexus3"
ports:
- "8081:8081"
volumes:
- nexus:/nexus-data
environment:
NEXUS_CONTEXT: "nexus"
nginx:
build: ./nginx
ports:
- "80:80"
links:
- jenkins
- nexus
volumes:
jenkins:
nexus:
However, when running the containers, it halts with an error:-
ERROR: Circular dependency between nginx and jenkins
SOLUTION: ATTEMPT #2
In effort to prevent the circular dependency problem, we can set up a link between Jenkins and Nexus with the Nexus alias pointing to the hostname, which is server.
This way, Jenkins communicate directly with Nexus through http://server:8081/nexus/some/path and Nginx will stay out of it.
version: '2'
services:
jenkins:
image: "jenkinsci/jenkins"
ports:
- "8080:8080"
volumes:
- jenkins:/var/jenkins_home
environment:
JENKINS_OPTS: "--prefix=/jenkins"
links:
- nexus:${HOSTNAME}
nexus:
image: "sonatype/nexus3"
ports:
- "8081:8081"
volumes:
- nexus:/nexus-data
environment:
NEXUS_CONTEXT: "nexus"
nginx:
build: ./nginx
ports:
- "80:80"
links:
- jenkins
- nexus
volumes:
jenkins:
nexus:
This works without problem.
However, this configuration somewhat defeats the purpose of using Nginx because while the users may access Jenkins and Nexus without specifying custom ports, Jenkins has to communicate with Nexus using port 8081.
Furthermore, this Nexus port is fully exposed in the build logs in all Jenkins jobs.
SOLUTION: ATTEMPT #3
The last attempt is to configure Nginx with the hostname as a network alias.
version: '2'
services:
jenkins:
image: "jenkinsci/jenkins"
ports:
- "8080:8080"
volumes:
- jenkins:/var/jenkins_home
environment:
JENKINS_OPTS: "--prefix=/jenkins"
nexus:
image: "sonatype/nexus3"
ports:
- "8081:8081"
volumes:
- nexus:/nexus-data
environment:
NEXUS_CONTEXT: "nexus"
nginx:
build: ./nginx
ports:
- "80:80"
links:
- jenkins
- nexus
networks:
default:
aliases:
- ${HOSTNAME}
volumes:
jenkins:
nexus:
networks:
default:
This time, Jenkins is able to communicate successfully with Nexus through http://server/nexus/some/path and Nginx will handle the reverse proxy accordingly.
Leave a Reply