Lab Objectives
By the end of this lab you will have: written a Dockerfile from scratch, built an image, run a web server container with port mapping, verified it in a browser, and used exec/logs/inspect for diagnostics.
End-to-end hands-on lab — write a Node.js web app, create a production-quality Dockerfile, build the image, run it, and verify it works correctly.
By the end of this lab you will have: written a Dockerfile from scratch, built an image, run a web server container with port mapping, verified it in a browser, and used exec/logs/inspect for diagnostics.
# Create a project folder mkdir docker-lab && cd docker-lab # Initialize Node.js project npm init -y # Install Express npm install express
# server.js
const express = require('express')
const app = express()
const PORT = process.env.PORT || 3000
app.get('/', (req, res) => {
res.json({
message: 'Hello from Docker!',
hostname: require('os').hostname(),
timestamp: new Date().toISOString()
})
})
app.get('/healthz', (req, res) => res.json({ status: 'ok' }))
app.listen(PORT, () => console.log(`Server running on port ${PORT}`))
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('SIGTERM received')
process.exit(0)
})# Dockerfile FROM node:18-alpine WORKDIR /app # Copy deps first for layer cache COPY package*.json ./ RUN npm ci --only=production # Copy application code COPY server.js . # Non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD wget -qO- http://localhost:3000/healthz || exit 1 CMD ["node", "server.js"]
# .dockerignore node_modules .git .env *.log
# Build the image
docker build -t mywebapp:1.0 .
# Verify image was created
docker image ls mywebapp
# Run the container
docker run -d \
--name mywebapp \
-p 8080:3000 \
--memory 256m \
mywebapp:1.0
# Check it is running
docker ps
# Test in browser or with curl
curl http://localhost:8080
# Expected: {"message":"Hello from Docker!","hostname":"...","timestamp":"..."}# View logs
docker logs mywebapp
# Check health status
docker inspect --format "{{.State.Health.Status}}" mywebapp
# Exec into the running container
docker exec -it mywebapp /bin/sh
# Inside: ps aux, env, ls -la /app
# Type 'exit' to leave
# Check resource usage
docker stats mywebapp --no-stream
# View image layers
docker image history mywebapp:1.0# Stop and remove container docker stop mywebapp docker rm mywebapp # Remove image docker rmi mywebapp:1.0 # Remove all stopped containers docker container prune
docker buildlocalhost:8080docker logs/metrics endpoint returning CPU and memory stats.node:18 vs node:18-alpine base.