DevOps Day 41: Creating a Custom Apache Image with a Dockerfile¶
Today's task was a deep dive into the most fundamental skill in the Docker ecosystem: building a custom image from scratch using a Dockerfile. My objective was to create a "recipe" that would take a base Ubuntu image, install the Apache web server, and configure it to run on a custom port.
This process is the foundation of creating portable, reproducible application environments. I learned how to codify the server setup into a simple text file, which is a core practice of "Infrastructure as Code." This document is my first-person guide to that entire process.
The Task¶
My objective was to create a custom Docker image on App Server 2. The specific requirements for the image were:
- The Dockerfile must be located at /opt/docker/Dockerfile.
- The base image must be ubuntu:24.04.
- The final image must have apache2 installed.
- The Apache server must be configured to listen on port 6300.
My Step-by-Step Solution¶
-
Prepare the Environment: I first connected to App Server 2 (
ssh steve@stapp02). The task required theDockerfileto be in a specific location, so I created the directory first. Since/optis owned byroot, I neededsudo.sudo mkdir -p /opt/docker -
Create the
Dockerfile: I created and edited theDockerfileusingvi.Inside the editor, I wrote the following instructions:sudo vi /opt/docker/Dockerfile# Start from the specified Ubuntu base image FROM ubuntu:24.04 # Run commands to update package lists and install apache2 RUN apt-get update && apt-get install -y apache2 # Run a command to modify the Apache port configuration file RUN sed -i 's/Listen 80/Listen 6300/g' /etc/apache2/ports.conf # Document the port the container will listen on EXPOSE 6300 # Set the default command to start Apache in the foreground CMD ["apache2ctl", "-D", "FOREGROUND"] -
Verification (Optional but Recommended): Although the task was just to create the file, I wanted to prove it worked.
- First, I built the image:
cd /opt/docker && sudo docker build -t my-apache:test . - Then, I ran a container from it, mapping the ports:
sudo docker run -d -p 8080:6300 --name test-app my-apache:test - Finally, I tested it with
curl http://localhost:8080, which returned the default Apache page, confirming myDockerfilewas perfect.
- First, I built the image:
Key Concepts (The "What & Why")¶
Dockerfile: This is a simple text file that contains a script of instructions for building a Docker image. It's the standard for creating reproducible and automated container builds. By putting my environment setup in aDockerfile, I ensure that anyone on my team can create the exact same image.FROM ubuntu:24.04: This is the foundation. EveryDockerfilemust start with aFROMinstruction, specifying the base image to build upon.RUNinstruction: This command executes a shell command inside the image during the build process. EachRUNinstruction creates a new layer in the image, which is a key concept for build caching and efficiency.CMDand Foreground Processes: TheCMDinstruction sets the default command to run when a container starts. A critical lesson is that for a service like a web server, this command must run in the foreground. If the command runs in the background, the container will think its main process has finished and will immediately exit.apache2ctl -D FOREGROUNDis the standard way to achieve this for Apache.
Commands I Used¶
sudo mkdir -p /opt/docker: Creates the required directory. The-pflag creates parent directories if they don't exist, which is a good habit.sudo vi /opt/docker/Dockerfile: Creates and edits theDockerfilewith root privileges.sudo docker build -t [name:tag] .: The command to build an image from aDockerfile.-t: Tags the image with a human-readable name..: Specifies that the build context (the files and theDockerfile) is the current directory.
sudo docker run -d -p [host_port]:[container_port] [image_name]: Runs a container from the newly built image, which I used for verification. q