Docker makes deployment simple, but simple does not automatically mean secure. A container is not a security mechanism, it is an isolation mechanism. What runs inside is up to you. These six measures take less than an hour combined, but they close the most common attack vectors we see in production. 1. Do Not Run as Root By default, every container process runs as root (UID 0). If an attacker escapes the container, they have root privileges on the host. FROM node:20-alpine WORKDIR /app COPY . . RUN npm ci --omit=dev RUN addgroup -S app && adduser -S app -G app USER app CMD ["node", "server.js"] 2. Read-Only Filesystem A container that cannot write cannot drop malware, manipulate configuration, or install a backdoor. services: api: image: myapp:latest read_only: true tmpfs: - /tmp - /run 3. Never Mount the Docker Socket Mounting the Docker socket into a container gives it full control over the entire Docker daemon and therefore the host. # Never do this: volumes: - /var/run/docker.sock:/var/run/docker.sock 4. Set Resource Limits Without limits, a single compromised container can bring down the entire host. services: worker: image: myworker:latest mem_limit: 512m memswap_limit: 512m cpus: "0.5" pids_limit: 100 5. Do Not Bake Secrets into the Image ENV DB_PASSWORD=supersecret in your Dockerfile ends up in every image layer, is visible in docker inspect, and gets stored in container registries forever. # Never do this: ENV DB_PASSWORD=mypassword123 # Pass at runtime: docker run --env-file .env myapp:latest 6. Scan Images Regularly Every image is a snapshot. Dependencies that are secure today may have known CVEs tomorrow. # Docker Scout (install plugin if needed): # docker scout install docker scout cves myapp:latest # Trivy: trivy image myapp:latest Conclusion Containerization gives you isolation, not security. These six measures are the minimum requirements for any production Docker workload.