Dockerfile
Getting started
A Dockerfile is a script that contains a set of instructions to automate the creation of Docker container images. It defines the base image, dependencies, configurations and commands needed to build and run an application inside a container.
References
Creating a Dockerfile
To create a Dockerfile
, follow these steps:
-
Make directory
Terminal window mkdir my-docker-project && cd my-docker-project -
Create a
Dockerfile
Terminal window nano Dockerfile -
Edit the
Dockerfile
Dockerfile # Use a base imageFROM node:20-alpine# Set working directoryWORKDIR /app# Copy package files and install dependenciesCOPY package.json package-lock.json ./RUN npm install --only=production# Copy application sourceCOPY . .# Expose port and define start commandEXPOSE 3000CMD ["node", "server.js"]
Build the image
Once your Dockerfile
is ready, build the image using the following command:
docker build -t my-app .
-t my-app
gives the image a name (my-app
)..
specifies the build context (current directory).
To verify the built image:
docker images
Running the container
To run a container from the built image:
docker run -d -p 3000:3000 --name my-running-app my-app
-d
runs the container in detached mode.-p 3000:3000
maps the container port to the host.--name my-running-app
assigns a name to the running container.
To check running containers:
docker ps
To stop the container:
docker stop my-running-app
Optimizing with Slim
Slim (SlimToolkit) helps reduce Docker image size by removing unnecessary files and dependencies and by improving the overall security and performance of the image.
-
Install
Terminal window curl -sLf https://raw.githubusercontent.com/slimtoolkit/slim/master/scripts/install-slim.sh | sudo sh -
Run Slim
Terminal window slim build --target my-app --tag my-app-slim -
Check the size difference
Terminal window docker images -
Run the optimized image
Terminal window docker run -d -p 3000:3000 my-app-slim
Buildx
If you need to build an image for a different CPU architecture (e.g., ARM on an x86 machine), you can use Docker buildx. Buildx supports multi-platform builds and allows you to cross-compile images. This ensures your image can run on multiple architectures without needing native hardware.
Enable buildx
Ensure buildx is enabled:
docker buildx create --use
Build for a specific architecture
To build an image for an ARM64 architecture:
docker buildx build --platform linux/arm64 -t my-app-arm64 .
Build multi-platform images
To build for multiple architectures at once:
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t my-multiarch-app .
If pushing to a registry (e.g., Docker Hub), add --push
:
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t my-dockerhub-user/my-multiarch-app --push .
Example Dockerfile
This Dockerfile leverages multi-stage builds, dependency caching and a non-root user to create a secure, lightweight and efficient container.
# Stage 1: BuildFROM node:20-alpine AS builder
# Set working directoryWORKDIR /app
# Copy package.json and package-lock.jsonCOPY package.json package-lock.json ./
# Install dependencies with caching optimizationRUN npm ci --only=production && npm cache clean --force
# Copy the rest of the application filesCOPY . .
# Build the application (if needed)RUN npm run build
# Stage 2: Production-ready ImageFROM node:20-alpine
# Create and use a non-root user for securityRUN addgroup -S appgroup && adduser -S appuser -G appgroupUSER appuser
# Set working directoryWORKDIR /app
# Copy built app and dependencies from builder stageCOPY --from=builder /app ./
# Expose application portEXPOSE 3000
# Use a non-root user for running the applicationCMD ["node", "server.js"]
-
Multi-stage build
- The first stage (
builder
) installs dependencies and builds the app. - The final stage only includes the necessary files, reducing image size.
- The first stage (
-
Dependency caching
npm ci --only=production
ensures reproducibility and avoids unnecessary package installations.- Copying
package.json
before other files allows Docker to cache dependencies efficiently.
-
Security enhancements
- Non-root user: Runs the container with a dedicated user instead of
root
, reducing attack vectors. - Minimal base image: Uses
node:20-alpine
to keep the image small and secure.
- Non-root user: Runs the container with a dedicated user instead of