
Docker is an open-source containerization platform that enables developers to package applications and all their dependencies into lightweight, portable containers that can run consistently across different environments. Docker images are the blueprint for containers. They package your application code, dependencies, environment variables, and runtime configurations into a portable and reproducible format. Building a Docker image allows you to encapsulate your application and run it consistently across different environments.
This article explains how to build Docker images efficiently and create an optimized Dockerfile.
If you're already familiar with Docker and just need a quick reference, use the following commands:
Continue reading for detailed explanations and examples of each command.
To build a Docker image, start by creating a Dockerfile. This file defines the environment, dependencies, and commands needed to build your application into a container image. Follow the steps below to create a Dockerfile for a Node.js web application.
Create a file named Dockerfile in your project's root directory.
Add the following content to the file.
Save and exit the file.
The above Dockerfile follows several best practices:
With your Dockerfile ready, use the docker buildx build command to create your image. Docker Buildx enables advanced build features such as multi-platform support, build caching, and pushing to registries.
Basic build with tag
Build with multiple tags and build arguments.
Multi-platform build and push to registry.
To build images for multiple CPU architectures and push them to a registry, use the docker buildx command to create and bootstrap a builder (one-time setup).
After the container-builder is running, you can run the multi-platform build.
Explanation of key options used with docker buildx build:
docker buildx build: Uses Docker BuildKit’s extended build command for advanced features like multi-platform builds and better caching.-t my-app:latest: Tags the image with a name (my-app) and version (latest).-t my-app:1.0: Adds another tag (1.0) to the image.--build-arg ENV=production: Passes build-time variable ENV with the value production into the Dockerfile.--platform linux/amd64,linux/arm64: Builds images for multiple CPU architectures (for example, x86_64 and ARM64).--push: Pushes the built and manifest list to the specified container registry.--no-cache: Forces the build to skip caching and build each layer from scratch.--pull: Always pulls the latest version of the base image instead of using the cached one.-f Dockerfile.prod: Specifies a custom Dockerfile (Dockerfile.prod) instead of the default Dockerfile..: Sets the build context to the present directory.Follow this example to build and tag a Docker image for a Node.js application:
Clone an example Docker Node.js application repository.
Navigate to the cloned project directory.
Create a Dockerfile inside the project root directory.
Add the following content to the file.
Build the Docker image.
View the newly built Docker image.
The above command lists all the Docker images available on your system.
How does the Docker Build Work:
Dockerfile in a layered fashion.node:22-alpine in this case).COPY, RUN, CMD).After building your Docker image, test it by running a container and verifying that your application behaves as intended.
Run a container from your image.
In the above command:
docker container run: Starts a container from an image.-d: Runs the container in detached mode (in the background).-p 3000:3000: Maps port 3000 of the host to port 3000 of the container.--name check-list-app: Assigns a custom name to the container.my-app:latest: Specifies the image and tag to use.Verify the container is running.
This command lists all running containers. After confirming your container is listed and running, you can access your application to ensure it behaves as expected.
Check the application logs for debugging purposes.
This command displays the container's logs, allowing you to verify application startup messages or troubleshoot any issues.
Stop and remove the container.
The above commands above stop the running container and then remove it entirely from your system.
Optimizing Docker image size leads to faster deployments, lower storage costs, and improved security. Follow these best practices to create smaller, more efficient Docker images.
Multi-stage builds let you create lean final images by separating build and runtime environments. Each FROM starts a new build stage, allowing you to copy only necessary artifacts into the final image.
The final image includes only the compiled binary and runtime dependencies, excluding source code and build tools.
Using smaller base images helps reduce Docker image size, improve security, and speed up build and deployment times. Choose a base image that includes only the essential components needed to run your application.
Best practices:
alpine or slim based images as a minimal base for building dependencies.distroless for a secure, production-ready runtime image.Go or Rust.PYTHONPATH to locate dependencies at runtime.Each instruction in a Dockerfile creates a new layer. Fewer, optimized layers reduce image size and speed up builds.
In the above Dockerfile:
In the above dockerfile:
&& to reduce layers..dockerignore FileExclude unnecessary files and directories from the Docker build context to reduce image size and speed up build times.
In the above .dockerignore file:
Docker caches image layers to avoid rebuilding unchanged steps. Structure your Dockerfile to take full advantage of this.
Best practices:
In the above Dockerfile:
You have built your own Docker image using the docker buildx build command and tested your Docker image by running a container. You learned how to create a custom Dockerfile to define your application environment, optimize your Docker images for size and performance. For more information, refer to the Docker documentation.
0 Comments
Be the first to comment and share your perspective with the community.