📖 Scenario: You are working on a simple web application using Docker. You want to create two Dockerfiles: one for development with debugging tools and live reload, and one for production optimized for performance and smaller size.
🎯 Goal: Build two Dockerfiles named Dockerfile.dev and Dockerfile.prod with specific content for development and production environments.
📋 What You'll Learn
Create a Dockerfile.dev starting from python:3.12-slim image
Add installation of flask and debugpy in Dockerfile.dev
Create a Dockerfile.prod starting from python:3.12-alpine image
Add installation of only flask in Dockerfile.prod
Use CMD to run app.py in both Dockerfiles
💡 Why This Matters
🌍 Real World
Developers often need different Docker setups for development and production to optimize debugging and performance.
💼 Career
Understanding how to write and manage multiple Dockerfiles is essential for DevOps roles and software deployment pipelines.
Progress0 / 4 steps
1
Create the development Dockerfile
Create a file named Dockerfile.dev with these exact lines: FROM python:3.12-slim RUN pip install flask debugpy COPY app.py /app.py CMD ["python", "/app.py"]
Docker
Hint
Use FROM to set the base image, RUN to install packages, COPY to add your app, and CMD to run it.
2
Create the production Dockerfile
Create a file named Dockerfile.prod with these exact lines: FROM python:3.12-alpine RUN pip install flask COPY app.py /app.py CMD ["python", "/app.py"]
Docker
Hint
Use a smaller base image python:3.12-alpine and install only flask for production.
3
Add a comment explaining the difference
Add a comment at the top of Dockerfile.dev that says: # Development Dockerfile with debug tools and a comment at the top of Dockerfile.prod that says: # Production Dockerfile optimized for size
Docker
Hint
Comments start with # and explain the purpose of each Dockerfile.
4
Display the content of both Dockerfiles
Print the content of Dockerfile.dev and Dockerfile.prod exactly as created, separated by a blank line.
Docker
Hint
Use triple quotes to store multi-line strings and print() to display them.
Practice
(1/5)
1. Why do we use separate Dockerfiles for development and production environments?
easy
A. Because development needs debugging tools and production needs optimized images
B. Because production requires more debugging tools than development
C. Because development images must be smaller than production images
D. Because production Dockerfiles always include all source code
Solution
Step 1: Understand development Dockerfile purpose
Development Dockerfiles include debugging tools and full dependencies to help developers test and debug easily.
Step 2: Understand production Dockerfile purpose
Production Dockerfiles are optimized for smaller size, speed, and security, removing unnecessary tools.
Final Answer:
Because development needs debugging tools and production needs optimized images -> Option A
Quick Check:
Separate Dockerfiles fit different environment needs [OK]
Hint: Dev needs tools; prod needs speed and security [OK]
Common Mistakes:
Thinking production needs more debugging tools
Assuming development images must be smaller
Believing production always includes all source code
2. Which of the following is a correct way to specify a base image in a production Dockerfile?
easy
A. BASE node:alpine
B. FROM node:latest
C. FROM alpine:node
D. FROM node:alpine
Solution
Step 1: Identify correct Dockerfile syntax for base image
The correct keyword to specify a base image is 'FROM', followed by the image name and tag.
Step 2: Choose a lightweight base image for production
For production, 'node:alpine' is a lightweight image suitable for smaller, optimized containers.
Final Answer:
FROM node:alpine -> Option D
Quick Check:
Use 'FROM' and lightweight image for production [OK]
Hint: Use 'FROM' and lightweight tags like alpine for production [OK]
Common Mistakes:
Using 'BASE' instead of 'FROM'
Incorrect image name order like 'alpine:node'
Using 'latest' tag for production images
3. Given this production Dockerfile snippet:
FROM node:alpine
WORKDIR /app
COPY package.json ./
RUN npm install --production
COPY . .
CMD ["node", "server.js"]
What is the main effect of the npm install --production command?
medium
A. Installs all dependencies including devDependencies
B. Installs no dependencies at all
C. Installs only production dependencies, skipping devDependencies
D. Installs only devDependencies
Solution
Step 1: Understand npm install --production flag
The '--production' flag tells npm to install only dependencies needed for running the app, skipping devDependencies used for development.
Step 2: Relate to production Dockerfile purpose
Skipping devDependencies reduces image size and improves security for production environments.
Final Answer:
Installs only production dependencies, skipping devDependencies -> Option C
Quick Check:
npm install --production = only production deps [OK]
Confusing devDependencies with production dependencies
4. You have a development Dockerfile that installs extra debugging tools but your production image is unexpectedly large. What is a likely cause?
medium
A. You used the development Dockerfile to build the production image
B. You forgot to copy source code in production Dockerfile
C. You used a smaller base image in production
D. You ran npm install without --production flag in development
Solution
Step 1: Identify cause of large production image
If the production image is large, it may include unnecessary development tools and dependencies.
Step 2: Check which Dockerfile was used for production build
Using the development Dockerfile for production will include extra tools, increasing image size.
Final Answer:
You used the development Dockerfile to build the production image -> Option A
Quick Check:
Wrong Dockerfile causes large production image [OK]
Hint: Use correct Dockerfile for each environment [OK]
Common Mistakes:
Assuming missing source code causes large image
Thinking smaller base image increases size
Confusing npm install flags in development
5. You want to create a multi-stage Dockerfile that uses a full Node.js image for development and a lightweight Alpine image for production. Which snippet correctly achieves this?
hard
A. FROM node:alpine AS build
WORKDIR /app
COPY . .
RUN npm install
FROM node:alpine
COPY --from=build /app .
CMD ["node", "server.js"]
B. FROM node:latest AS build
WORKDIR /app
COPY . .
RUN npm install
FROM node:alpine
COPY --from=build /app .
CMD ["node", "server.js"]
C. FROM node:alpine AS build
WORKDIR /app
COPY . .
RUN npm install --production
FROM node:latest
COPY --from=build /app .
CMD ["node", "server.js"]
D. FROM node:latest
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
Solution
Step 1: Identify multi-stage build structure
The first stage uses a full Node.js image (node:latest) for building with all tools, suitable for development.
Step 2: Use lightweight Alpine image for final production stage
The second stage uses node:alpine to copy only necessary files from build stage, creating a smaller production image.
Step 3: Verify correct order and commands
FROM node:latest AS build
WORKDIR /app
COPY . .
RUN npm install
FROM node:alpine
COPY --from=build /app .
CMD ["node", "server.js"] correctly uses 'AS build' for first stage and copies from it to the lightweight image.
Final Answer:
FROM node:latest AS build
WORKDIR /app
COPY . .
RUN npm install
FROM node:alpine
COPY --from=build /app .
CMD ["node", "server.js"] -> Option B
Quick Check:
Multi-stage: full image build + alpine production [OK]
Hint: Use full image first, then alpine with COPY --from=build [OK]
Common Mistakes:
Using alpine for build stage losing dev tools
Using latest image for final production stage
Not using multi-stage COPY syntax
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.