Creating Custom Foundational Docker Images

CentOS 7 Base Image

Network restrictions and misaligned configurations in public repositories make custom base images essential for streamlined workflows. Four configuration assets are required for this build.

[root@host centos7]$ ls
custom-epel.repo  custom-base.repo  Dockerfile  supervisord.cfg

Dockerfile

FROM centos:7.9.2009
LABEL maintainer="DevOps Team"

ENV TIMEZONE="Asia/Shanghai"
ENV TERMINAL="xterm"

COPY custom-base.repo /etc/yum.repos.d/CentOS-Base.repo
COPY custom-epel.repo /etc/yum.repos.d/epel.repo

RUN yum update -y && \
    yum install -y curl wget tar bzip2 unzip vim-enhanced passwd sudo yum-utils hostname net-tools rsync && \
    yum install -y gcc gcc-c++ git make automake cmake patch logrotate python3-devel && \
    yum install -y --enablerepo=epel pwgen python3-pip lrzsz && \
    yum clean all && \
    rm -rf /var/cache/yum

RUN pip3 install supervisor && \
    mkdir -p /etc/supervisord.d

COPY supervisord.cfg /etc/supervisord.conf

EXPOSE 22

CMD ["/usr/local/bin/supervisord", "-n", "-c", "/etc/supervisord.conf"]

Repository Files

custom-epel.repo

[epel]
name=Extra Packages for Enterprise Linux 7 - $basearch
baseurl=http://mirrors.example.com/epel/7/$basearch
failovermethod=priority
enabled=1
gpgcheck=0

custom-base.repo

[base]
name=CentOS-$releasever - Base
baseurl=http://mirrors.example.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=http://mirrors.example.com/centos/RPM-GPG-KEY-CentOS-7

[updates]
name=CentOS-$releasever - Updates
baseurl=http://mirrors.example.com/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=http://mirrors.example.com/centos/RPM-GPG-KEY-CentOS-7

Supervisor Configuration

[unix_http_server]
file=/var/run/supervisor.sock

[supervisord]
logfile=/var/log/supervisord.log
logfile_maxbytes=50MB
logfile_backups=10
loglevel=info
pidfile=/var/run/supervisord.pid
nodaemon=false
minfds=1024
minprocs=200

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock

[include]
files = /etc/supervisord.d/*.ini

Execute the build process. The trailing period specifies the current directory as the build context. Tag the image with the private registry hostname.

docker build -t registry.internal.com/infra/centos:7 .

docker images
REPOSITORY                        TAG       IMAGE ID       CREATED        SIZE
registry.internal.com/infra/centos   7         2e1f3e5b8a4c   1 minute ago   450 MB

docker push registry.internal.com/infra/centos:7

Launch the container:

docker run -d --name base-centos registry.internal.com/infra/centos:7

JDK Base Image

Official Java images typically rely on Debian, which may not suit environments standardizing on RHEL-based systems. Creating a custom JDK image resolves this dependency conflict.

[root@host jdk8]$ ls
Dockerfile  openjdk-8.tar.gz

Dockerfile

FROM registry.internal.com/infra/centos:7
LABEL maintainer="DevOps Team"

ADD openjdk-8.tar.gz /opt/java/

ENV JAVA_HOME=/opt/java/jdk8u352
ENV PATH="${PATH}:${JAVA_HOME}/bin"

Build and verify the Java installation:

docker build -t registry.internal.com/infra/jdk:8 .

docker run -dit --name jdk-test registry.internal.com/infra/jdk:8
docker exec jdk-test java -version
openjdk version "1.8.0_352"
OpenJDK Runtime Environment (build 1.8.0_352-b08)
OpenJDK 64-Bit Server VM (build 25.352-b08, mixed mode)

Tomcat Image

Three files are necessary for the Tomcat build, including a Supervisor configuration to manage the process.

[root@host tomcat]$ ls
Dockerfile  tomcat-supervisor.ini  apache-tomcat.tar.gz

Dockerfile

FROM registry.internal.com/infra/jdk:8
LABEL maintainer="DevOps Team"

ADD apache-tomcat.tar.gz /opt/
COPY tomcat-supervisor.ini /etc/supervisord.d/tomcat.ini

tomcat-supervisor.ini

[program:tomcat]
environment=JAVA_HOME="/opt/java/jdk8u352",JAVA_BIN="/opt/java/jdk8u352/bin"
command=/opt/tomcat/bin/catalina.sh run
autostart=true
autorestart=true
startsecs=10
priority=1
stopasgroup=true
killasgroup=true
redirect_stderr=true
stdout_logfile=/opt/tomcat/logs/catalina.out

Construct and deploy the container:

docker build -t registry.internal.com/infra/tomcat:9 .

docker run -d -p 8080:8080 --name tomcat-app registry.internal.com/infra/tomcat:9

Jenkins Image

Official Jenkins images often use Debian bases. Building a custom image on top of the CentOS/Tomcat layer ensures consistency across the infrastructure.

[root@host jenkins]$ ls
Dockerfile  maven-dist.tar.gz  jenkins.war

Dockerfile

FROM registry.internal.com/infra/tomcat:9
LABEL maintainer="DevOps Team"

ADD maven-dist.tar.gz /opt/
COPY jenkins.war /opt/tomcat/webapps/ROOT.war

ENV MAVEN_HOME=/opt/maven
ENV JENKINS_HOME=/data/jenkins
ENV PATH="${PATH}:${MAVEN_HOME}/bin"

Build the image:

docker build -t registry.internal.com/infra/jenkins:lts .

Standard launch:

docker run -d -p 8080:8080 --name jenkins-server registry.internal.com/infra/jenkins:lts

For continuous integration tasks, the container requires access to the host Docker daemon. Mounting the Docker socket and binary enables this functionality:

docker run -d -p 8080:8080 --name jenkins-server \
  -v /data/jenkins:/data/jenkins \
  -v /usr/bin/docker:/usr/bin/docker \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /etc/sysconfig/docker:/etc/sysconfig/docker \
  registry.internal.com/infra/jenkins:lts

Persisting the Jenkins home directory ensures that CI pipelines and configurations survive container recreation.

Tags: docker dockerfile centos JDK Tomcat

Posted on Sat, 27 Jun 2026 16:19:00 +0000 by teng84