Just some notes I put together to help keep me better organized. No guarentees made.
First things first, bring up an instance some where some how. We need access to root, including ports 22, and 443. Once that's up point your DNS A records to the public IP.
jenkins.hauntedmansion.io. 300 IN A 52.11.156.122
sonar.hauntedmansion.io. 300 IN A 52.11.156.122
I'm running in EC2 and using Amazon Linux. I followed these steps to bring up a docker environment which worked perfectly for my needs:
sudo yum update -y
sudo yum install docker git -y
sudo sysctl -w vm.max_map_count=262144
sudo sysctl -w fs.file-max=100000
sudo sh -c "echo 'vm.max_map_count=262144' >> /etc/sysctl.conf"
sudo sh -c "echo 'fs.file-max=100000' >> /etc/sysctl.conf"
sudo sysctl -p
sudo usermod -a -G docker ec2-user
sudo sh -c "echo \"OPTIONS='--default-ulimit nofile=65536:65536'\" >> /etc/sysconfig/docker"
newgrp docker
sudo service docker start
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version
Once your docker environment is online you can run a docker compose file. This will bring up 4 services and multiple mount points. Jenkins, Sonarqube, Postgres, and Nginx. All traffic is proxied via Nginx to the specific container. This configuration also provides a cert-bot capability and will automatically setup TLS once it's running and your A records can be resolved by the certificate issuer (Let's Encrypt).
Before running the docker compose file you'll want to have a couple of folders set up. I fought a battle with the Sonarqube container and lost. In a nutshell, it's installation expands itself (tar.gz) during the docker build. This prevents you from mounting the volume locally which I wanted to do. Sure, you can mount the volume, but now that dir is empty and Sonarqube cant function. So I ended up downloading the of version of Sonarqube I needed, unzipping it into my local directory and then using that as the mount point, I also had to copy the dockers run.sh script. I do not like this container. I may suggest that their entry script determine if the application is installed and if not expand on first run.
You can get the source here:
https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.9.1.zip
Sonarqube also has weird permissions so you may need to
chown -R 999:docker sonarqube/
I also created a conf.d directory for nginx with two files:
For Jenkins (conf.d/jenkins.conf):
server {
listen 443 ssl;
server_name jenkins.hauntedmansion.io;
ssl_certificate /etc/letsencrypt/live/jenkins.hauntedmansion.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jenkins.hauntedmansion.io/privkey.pem;
client_max_body_size 20M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://jenkins:8080;
proxy_read_timeout 90;
proxy_redirect http://127.0.0.1:8080 https://jenkins.hauntedmansion.io;
}
}
For Sonarqube: (conf.d/sonar.conf):
server {
listen 443 ssl;
server_name sonar.hauntedmansion.io;
ssl_certificate /etc/letsencrypt/live/sonar.hauntedmansion.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sonar.hauntedmansion.io/privkey.pem;
client_max_body_size 20M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://sonarqube:9000;
proxy_read_timeout 90;
proxy_redirect http://127.0.0.1:9000 https://sonar.hauntedmansion.io;
}
}
So far our project directory looks like this:
drwxr-xr-x 7 ec2-user docker 119 May 17 21:54 .
drwx------ 5 ec2-user ec2-user 138 May 17 19:06 ..
drwxr-xr-x 2 ec2-user docker 44 May 17 19:06 conf.d
drwxr-xr-x 12 libstoragemgmt docker 191 May 16 20:01 sonarqube
You will also need to copy that docker run.sh
to sonarqube/bin
. You can grab it here:
Last but not least, the docker-compose.yml
I used to bring it all up.
version: "3"
services:
nginx:
container_name: nginx-certbot
restart: unless-stopped
image: staticfloat/nginx-certbot
networks:
- local
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
environment:
CERTBOT_EMAIL: cvega@github.com
volumes:
- ./conf.d:/etc/nginx/user.conf.d:ro
- letsencrypt:/etc/letsencrypt
sonarqube:
image: sonarqube:7.9.1-community
user: "999"
networks:
- local
environment:
- SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar
- SONARQUBE_JDBC_USERNAME=sonar
- SONARQUBE_JDBC_PASSWORD=sonar
volumes:
- ./sonarqube:/opt/sonarqube
db:
image: postgres
networks:
- local
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- ./postgresql:/var/lib/postgresql
- ./postgresql_data:/var/lib/postgresql/data
jenkins:
image: jenkins/jenkins:2.222.1
networks:
- local
volumes:
- ./jenkins:/var/jenkins_home
networks:
local:
volumes:
letsencrypt:
If all goes well you can run the following and visit your sites in a few moments:
docker-compose -f "docker-compose.yml" up --build
You end up with a directory that looks like this once the cluster is up, you can access all of the important pieces of the applications locally.
drwxr-xr-x 7 ec2-user docker 119 May 17 21:54 .
drwx------ 5 ec2-user ec2-user 138 May 17 19:06 ..
drwxr-xr-x 2 ec2-user docker 44 May 17 19:06 conf.d
-rw-r--r-- 1 ec2-user docker 1086 May 16 20:49 docker-compose.yml
drwxr-xr-x 23 ec2-user docker 4096 May 17 19:47 jenkins
drwxr-xr-x 3 ec2-user docker 18 May 16 19:37 postgresql
drwx------ 19 libstoragemgmt docker 4096 May 16 21:26 postgresql_data
drwxr-xr-x 12 libstoragemgmt docker 191 May 16 20:01 sonarqube
Last but not least, script format to make this even easier (not saying this is universal but it worked on EC2 base Amazon 2 Linux m5.xlarge instance)
#!/usr/bin/env bash
sudo yum update -y
sudo yum install docker git -y
sudo sysctl -w vm.max_map_count=262144
sudo sysctl -w fs.file-max=100000
sudo sh -c "echo 'vm.max_map_count=262144' >> /etc/sysctl.conf"
sudo sh -c "echo 'fs.file-max=100000' >> /etc/sysctl.conf"
sudo sysctl -p
sudo usermod -a -G docker ec2-user
sudo sh -c "echo \"OPTIONS='--default-ulimit nofile=65536:65536'\" >> /etc/sysconfig/docker"
newgrp docker
sudo service docker start
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version
mkdir project
cd project
mkdir -p conf.d/
curl -L https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.9.1.zip -o sonarqube-7.9.1.zip
unzip sonarqube-7.9.1.zip
mv sonarqube-7.9.1/ sonarqube/
curl -L https://raw.githubusercontent.com/SonarSource/docker-sonarqube/82aff0792a91eb1a58baea66e7651c8e69fa18ce/7.9.1-community/run.sh
-o sonarqube/bin/run.sh
sudo chown -R 999:docker sonarqube/
JENKINS="conf.d/jenkins.conf"
/bin/cat <<EOM >$JENKINS
server {
listen 443 ssl;
server_name jenkins.hauntedmansion.io;
ssl_certificate /etc/letsencrypt/live/jenkins.hauntedmansion.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jenkins.hauntedmansion.io/privkey.pem;
client_max_body_size 20M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://jenkins:8080;
proxy_read_timeout 90;
proxy_redirect http://127.0.0.1:8080 https://jenkins.hauntedmansion.io;
}
}
EOM
SONAR="conf.d/sonar.conf"
/bin/cat <<EOM >$SONAR
server {
listen 443 ssl;
server_name sonar.hauntedmansion.io;
ssl_certificate /etc/letsencrypt/live/sonar.hauntedmansion.io/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/sonar.hauntedmansion.io/privkey.pem;
client_max_body_size 20M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://sonarqube:9000;
proxy_read_timeout 90;
proxy_redirect http://127.0.0.1:9000 https://sonar.hauntedmansion.io;
}
}
EOM
DOCKER="docker-compose.yml"
/bin/cat <<EOM >$DOCKER
version: "3"
services:
nginx:
container_name: nginx-certbot
restart: unless-stopped
image: staticfloat/nginx-certbot
networks:
- local
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
environment:
CERTBOT_EMAIL: cvega@github.com
volumes:
- ./conf.d:/etc/nginx/user.conf.d:ro
- letsencrypt:/etc/letsencrypt
sonarqube:
image: sonarqube:7.9.1-community
user: "999"
networks:
- local
environment:
- SONARQUBE_JDBC_URL=jdbc:postgresql://db:5432/sonar
- SONARQUBE_JDBC_USERNAME=sonar
- SONARQUBE_JDBC_PASSWORD=sonar
volumes:
- ./sonarqube:/opt/sonarqube
db:
image: postgres
networks:
- local
environment:
- POSTGRES_USER=sonar
- POSTGRES_PASSWORD=sonar
volumes:
- ./postgresql:/var/lib/postgresql
- ./postgresql_data:/var/lib/postgresql/data
jenkins:
image: jenkins/jenkins:2.222.1
networks:
- local
volumes:
- ./jenkins:/var/jenkins_home
networks:
local:
volumes:
letsencrypt:
EOM
docker-compose -f "docker-compose.yml" up --build