Infrastructure Reinstall

The final step of our Infrastructure Seed process creates the "infrastructure grade" Nexus3 Docker images that are based off assets coming from our own DML. The following images will now be created:

  1. (prior step) Ubuntu Base Image with APT template
  2. (prior step) OpenJDK8 with our own copy of the JDK and APT proxy
  3. Nexus3 with our own copy of the install package and APT proxy

Nexus3 Image

This being our third Nexus3 image as part of this lab, it is finally considered our Production grade image that will be used as a baseline for Nexus3 updates in the future.

labimagesnexus
version: '3.3'

services:
  nexus:
    image: infra/sonatype/nexus3:1.0.0
    build:
      context: .
      network: host
      args:
        ARG_ART_URL: http://d1i-doc-ngbuild:3001
      extra_hosts:
        - "d1i-doc-ngbuild:172.22.90.2"
FROM infra/java/openjdk-8:1.0.0

ARG CONTAINER_UID=2001
ARG CONTAINER_GID=2001
ARG CONTAINER_USER=nexus
ARG CONTAINER_GROUP=nexus

RUN groupadd -g ${CONTAINER_GID} ${CONTAINER_GROUP} \
    && useradd -d /home/${CONTAINER_USER} -u ${CONTAINER_UID} -g ${CONTAINER_GROUP} -m -s /bin/bash ${CONTAINER_USER}
    
RUN mkdir -p /opt/sonatype/nexus /opt/sonatype/sonatype-work/nexus3 \
    && ln -s /opt/sonatype/sonatype-work/nexus3 /nexus-data \
    && chown -R nexus:nexus /opt/sonatype /nexus-data

ARG NEXUS_VERSION=3.41.0-01

ARG ARG_ART_URL

RUN curl $ARG_ART_URL/repository/dml/docker/nexus/nexus-${NEXUS_VERSION}-unix.tar.gz -o /tmp/nexus-${NEXUS_VERSION}-unix.tar.gz \
    && tar -xvzf /tmp/nexus-${NEXUS_VERSION}-unix.tar.gz --strip-components=1 -C /opt/sonatype/nexus \
    && rm -rf /tmp/*

USER nexus

CMD ["/opt/sonatype/nexus/bin/nexus","run"]

NGINX as Reverse Proxy

Before completing the Nexus3 Repository installation, we want to change our run behavior to ensure its SSL protected by running it behind nginx. As the name of the image suggests, it is considered a base image that can be used to dynamically adjust containers we want to run behind this nginx generally via a subdomain.acme.com. This is accomplished via a wildcard config include inside the nginx.conf.

labimagesnginx-base
daemon off;
worker_processes  1;

#error_log  /var/log/nginx/error.log warn;
#pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {

    proxy_send_timeout 120;
    proxy_read_timeout 300;
    proxy_buffering    off;
    keepalive_timeout  5 5;
    tcp_nodelay        on;

    include /etc/nginx/conf.d/*.conf;
}
version: '3.3'

services:
  nginx:
    image: infra/nginx/base:1.0.0
    build:
      context: .
      network: host
      args:
        ARG_ART_URL: http://d1i-doc-ngbuild:3001
      extra_hosts:
        - "d1i-doc-ngbuild:172.22.90.2"
FROM infra/ubuntu/focal:1.0.0

ARG ARG_ART_URL

RUN sed -e "s|APT_URL|${ARG_ART_URL}|" /etc/apt/sources.list.base > /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y nginx=1.18.* \
    && apt-get clean \
    && rm /etc/apt/sources.list

# Add default configuration
COPY conf/nginx.conf /etc/nginx/nginx.conf

CMD ["nginx"]

Next, we want to use a wildcard self signed SSL for *.acme.com, allowing us to run many of our DevOps apps behind the same nginx as we continue. As you should always try to externalize your ssl, we are going to use a ssl generator tool image.

labtoolsssl-cert
version: '3.3'

services:
  ssl-cert:
    image: tools/ssl-cert:1.0.0
    build:
      context: .
      network: host
      args:
        ARG_ART_URL: http://d1i-doc-ngbuild:3001
      extra_hosts:
        - "d1i-doc-ngbuild:172.22.90.2"
FROM infra/ubuntu/focal:1.0.0

ARG ARG_ART_URL

RUN sed -e "s|APT_URL|${ARG_ART_URL}|" /etc/apt/sources.list.base > /etc/apt/sources.list \
    && apt-get update \
    && apt-get install -y openssl dos2unix \
    && apt-get clean \
    && rm /etc/apt/sources.list

COPY init.sh /init/init.sh
RUN chmod +x /init/init.sh \
    && dos2unix /init/init.sh

ENTRYPOINT ["/init/init.sh"]
#!/bin/bash

# fail if anything errors
set -e

openssl req -x509 -newkey rsa:4096 \
    -subj "/C=XX/ST=XXXX/L=XXXX/O=XXXX/CN=${CERT_CN}" \
    -keyout "/ssl/${KEY_NAME}" \
    -out "/ssl/${CERT_NAME}" \
    -days 365 -nodes -sha256

We will be creating the wildcard certificate using the following compose file. Once generated, the certificate will be placed into the nginx compose location.

labcomposed
version: '3.3'

services:
  ssl-cert:
    image: tools/ssl-cert:1.0.0
    volumes:
      - ./ssl:/ssl
    environment:
      - CERT_CN=*.acme.com
      - KEY_NAME=key.pem
      - CERT_NAME=cert.pem
    networks:
      - ops-network
networks:
  ops-network:
    name: ops-network

Building & Running the Final Images

Build the Nexus3 and NGINX. Remember we still rely on our Nginx build proxy for the docker compose build files.

docker-compose -f images/nexus/docker-compose.yml build
docker-compose -f images/nginx-base/docker-compose.yml build
docker-compose -f tools/ssl-cert/docker-compose.yml build

Next is adding both nexus and nginx as individual compose files. Note, we are adding a specific IP address for the nginx as we want to leverage hostfile additions to other docker containers in other parts of the lab to simplify DNS.

labcomposed
version: '3.3'

services:
  nexus:
    image: infra/sonatype/nexus3:1.0.0
    volumes:
      - nexus-data:/nexus-data
    ports:
      # this is for HTTP web interface
      - 8081:8081
      # this is for HTTP docker combined registry 
      - 8082:8082
      # this is for HTTP docker private registry 
      - 8083:8083
    hostname: d1i-doc-nexus01
    networks:
      - ops-network
networks:
  ops-network:
    name: ops-network
volumes:
  nexus-data:
    name: nexus-data
labcomposed
server {
    listen       *:443 ssl;
    server_name  "nexus.acme.com";

    ssl_certificate           /etc/nginx/external/cert.pem;
    ssl_certificate_key       /etc/nginx/external/key.pem;

    client_max_body_size 1G;

    location / {
        proxy_pass         http://d1i-doc-nexus01:8081;

        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 https;
    }
}

server {
    listen       *:443 ssl;
    server_name  "docker.acme.com";

    ssl_certificate           /etc/nginx/external/cert.pem;
    ssl_certificate_key       /etc/nginx/external/key.pem;

    client_max_body_size 1G;

    location / {
        proxy_pass         http://d1i-doc-nexus01:8082;

        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 https;
    }
}



server {
    listen       *:443 ssl;
    server_name  "docker-private.acme.com";

    ssl_certificate           /etc/nginx/external/cert.pem;
    ssl_certificate_key       /etc/nginx/external/key.pem;

    client_max_body_size 1G;

    location / {
        proxy_pass         http://d1i-doc-nexus01:8083;

        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 https;
    }
}
version: '3.3'

services:
  nginx:
    image: infra/nginx/base:1.0.0
    volumes:
      - ./ssl/cert.pem:/etc/nginx/external/cert.pem
      - ./ssl/key.pem:/etc/nginx/external/key.pem
      - ./nginx/nexus.conf:/etc/nginx/conf.d/nexus.conf
    ports:
      - 443:443
    hostname: d1i-doc-ng01
    networks:
      ops-network:
        ipv4_address: 172.22.90.1
networks:
  ops-network:
    name: ops-network
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.22.90.0/16

Stop the running non-nginx Nexus3 (http access based), our nginx build proxy and start the new SSL based Nexus3 containers (nginx + nexus3 + nginx-build).

# stop the seed
docker-compose -f composed/docker-compose-seed.yml stop

# generate wildcard cert
docker-compose -f composed/docker-compose-ssl-cert-wildcard.yml up

# start nexus
docker-compose -f composed/docker-compose-nexus.yml up --no-start
docker-compose -f composed/docker-compose-nexus.yml start

# start behind nginx
docker-compose -f composed/docker-compose-nginx-nexus.yml up --no-start
docker-compose -f composed/docker-compose-nginx-nexus.yml start

# check logs until started
docker-compose -f composed/docker-compose-nexus.yml logs -f --tail="50"

As the DML is using an nginx config with acme, ensure to change your host file to point nexus.acme.com to 127.0.0.1. After that change, your nexus installation is available at https://nexus.acme.com/.