Keywords: Docker | Java | Containerization
Abstract: This article explores how to build Docker images containing Java applications and enable automatic JAR file execution upon container startup. By analyzing the differences between RUN and CMD instructions in Dockerfile, it explains the lifecycle of image building and container running. The article details modifying Dockerfile to use CMD instruction, allowing containers to automatically execute Java applications without repeating commands in docker run. Additionally, it discusses best practices for container restart and image rebuilding to optimize Docker workflows.
Basic Concepts of Docker Images and Containers
In the Docker ecosystem, images and containers are two core but often confused concepts. An image is a static, read-only template that includes all files, dependencies, and configurations required to run an application. It is created once during the build process, typically defined by a Dockerfile. For example, the Dockerfile in the question uses FROM anapsix/alpine-java to specify the base image, then copies the JAR file into the image via the COPY instruction.
A container is a running instance of an image. When using the docker run command, Docker creates a writable container layer based on the image and starts a process within it. Containers are dynamic and can be started, stopped, restarted, or deleted. Understanding this distinction is crucial, as many beginners mistakenly believe that images themselves run applications, whereas applications execute within containers.
Difference Between RUN and CMD Instructions in Dockerfile
In the original Dockerfile, the RUN java -jar /home/testprj-1.0-SNAPSHOT.jar instruction was used. The RUN instruction executes during image build to install packages or run build scripts, with results persisted in image layers. This means the Java command runs once when building the image, outputting to the console, but the image does not contain a continuously running process.
In contrast, the CMD instruction specifies the default command to run when a container starts. It does not execute during build but serves as the container's entry point. Modifying the Dockerfile to use CMD, such as CMD ["java","-jar","/home/testprj-1.0-SNAPSHOT.jar"], ensures the JAR file runs automatically on container startup without explicitly specifying it in the docker run command. This simplifies container management and aligns application behavior with expectations.
Steps to Enable Automatic JAR File Execution
First, update the Dockerfile to use the CMD instruction. Here is an example code:
FROM anapsix/alpine-java
MAINTAINER myNAME
COPY testprj-1.0-SNAPSHOT.jar /home/testprj-1.0-SNAPSHOT.jar
CMD ["java","-jar","/home/testprj-1.0-SNAPSHOT.jar"]
The build command remains unchanged: docker build -t imageName .. After building, run the container by specifying only the image name without additional commands: docker run --name myProgram imageName. Upon startup, the container automatically executes the Java command defined in CMD, running the JAR file.
If the application needs restarting, use docker restart myProgram. This is more efficient than rerunning the full docker run command, as it reuses the existing container. When the application code is updated, rebuild the image: first remove the old image with docker rmi imageName, then rebuild with docker build -t imageName .. This ensures the image reflects the latest application state.
Additional Knowledge and Best Practices
Beyond CMD, ENTRYPOINT is another related instruction that can define the container's main process. Combining ENTRYPOINT and CMD allows for more flexible configurations. For example, set ENTRYPOINT to ["java","-jar"] and CMD to specify the JAR file path, enabling parameter overrides when running the container.
In real-world deployments, consider using Docker Compose or multi-stage builds to optimize image size and security. For instance, using Alpine base images can reduce volume, while multi-stage builds separate build and runtime environments for efficiency.
In summary, by correctly using Dockerfile instructions, developers can ensure Java applications run automatically in Docker containers, simplifying operational workflows. Understanding the lifecycle of images and containers is a key step in mastering Docker technology.