What is a Dockerfile?
A Dockerfile is a script consisting of a series of instructions and arguments used to automate the creation of a Docker image.
The Three-Step Build Process
- Create the Dockerfile: Define the build logic in a text file.
- Build the Image: Execute
docker buildto create the image from the file. - Run the Container: Launch the instance using
docker run.
Example Structure
Below is an example of a Dockerfile based on a standard CentOS image:
# Set the base image
FROM centos
# Metadata label
LABEL maintainer="devteam@example.com"
# Configure environment variable
ENV APP_DIR /opt/app
# Set the working directory
WORKDIR $APP_DIR
# Install necessary tools
RUN yum update -y && \
yum install -y vim net-tools
# Expose network port
EXPOSE 80
# Default command on startup
CMD ["echo", "Build successful!"]
CMD ["/bin/bash"]
Dockerfile Build Mechanics
Syntax Rules
- Instructions are written in uppercase (e.g.,
FROM,RUN) followed by arguments. - Commands are executed sequentially from top to bottom.
- Lines starting with
#are treated as comments. - Each instruction creates a new layer in the image filesystem.
Execution Flow
- Docker launches a temporary container from the base image.
- It executes the first instruction, modifying the container state.
- It commits the changes, creating a new image layer.
- Docker starts a new container based on that new layer.
- This repeats until all instructions are processed.
The Software Lifecycle
From a software perspective, these components represent different stages:
- Dockerfile: The raw material or blueprint (
devphase). - Docker Image: The packaged deliverable or artifact (
opsphase). - Docker Container: The running instance of the aplication.
Key Instructions and Cases
Base Images
Most images on Docker Hub are derived from a minimal base (often called scratch) where applications are installed and configured.
Customizing a CentOS Image
To enhance the default CentOS image with specific tools:
Build Command:
docker build -t my-custom-centos:latest .
Run Command:
docker run -it my-custom-centos:latest
Inspect History:
docker history my-custom-centos:latest
CMD vs ENTRYPOINT
- CMD: Defines default arguments. If you pass arguments to
docker run, they replace theCMDinstruction (only the lastCMDtakes effect).- Example: Running
docker run my-image ls -lwill executels -linstead of the default command.
- Example: Running
- ENTRYPOINT: Defines the executable that will always run. Arguments passed to
docker runare appended to theENTRYPOINT.
Case Study: IP Lookup Tool
Using curl to fetch IP data. If the image has a CMD set to curl -s http://ip.cn, running docker run ip-image -i will fail because -i replaces the command. To fix this, use ENTRYPOINT:
FROM centos
RUN yum install -y curl
ENTRYPOINT ["curl", "-s", "http://ip.cn"]
Now, docker run ip-image -i executes curl -s http://ip.cn -i.
Custom Tomcat 9 Deployment
Directory Setup:
mkdir -p /data/docker/tomcat9
cd /data/docker/tomcat9
# Place jdk and tomcat tarballs here
Dockerfile Content:
FROM centos
# Metadata
LABEL maintainer="admin@example.com"
# Copy context files
COPY c.txt /usr/local/container.txt
# Extract Java and Tomcat
ADD jdk-8u171-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.8.tar.gz /usr/local/
# Install editor
RUN yum install -y vim
# Set environment
ENV APP_HOME /usr/local
WORKDIR $APP_HOME
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin
# Expose port
EXPOSE 8080
# Startup logic
CMD ["catalina.sh", "run"]
Running with Volumes:
docker run -d -p 9080:8080 \
--name tomcat9-instance \
-v /data/docker/tomcat9/webapp:/usr/local/apache-tomcat-9.0.8/webapps/test \
-v /data/docker/tomcat9/logs:/usr/local/apache-tomcat-9.0.8/logs \
--privileged=true \
my-tomcat-image
Note: If permission errors occur during volume mounting, ensure the --privileged=true flag is used.
Web App Test
Create a simple test directory in the mounted volume with the following files:
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
version="2.5">
<display-name>Test App</display-name>
</web-app>
index.jsp:
<%@ page contentType="text/html; charset=UTF-8" %>
<html>
<body>
<h1>Docker Tomcat Test</h1>
<% System.out.println("Request received in container"); %>
</body>
</html>