DCA: Docker Certified Associate Study Guide
The Docker Certified Associate (DCA) validates real-world expertise operating Docker in production, spanning Swarm orchestration, image creation and registry management, engine installation and configuration, container networking, security hardening, and persistent storage. It is aimed at engineers, SREs, and DevOps practitioners with roughly 6-12 months of hands-on Docker experience. The 90-minute exam has multiple-choice and multiple-select questions, with a passing score around 65%.
Domain 1: Orchestration
- docker swarm init configures the current node as the first manager, generates the Raft cluster, and prints both manager and worker join tokens; retrieve them later with docker swarm join-token worker or docker swarm join-token manager.
- Swarm uses the Raft consensus protocol, requiring a quorum of (N/2)+1 managers; a 5-manager cluster tolerates loss of 2, a 3-manager cluster tolerates loss of 1. Always run an odd number of managers (3 or 5) and spread them across availability zones.
- In a network partition, only the side holding a quorum majority can commit writes (scheduling, scaling); the minority partition becomes read-only until quorum is restored.
- docker stack deploy -c docker-compose.yml mystack deploys a multi-service stack from a Compose file, applying deploy-key settings such as replicas, placement, and update_config.
- docker service scale web=5 and docker service update --replicas 5 web both set a replicated service to 5 tasks; replicated mode runs a fixed count, while global mode runs exactly one task on every matching node (ideal for monitoring/logging agents).
- When a node goes down, its tasks are rescheduled onto other available nodes and no new tasks are assigned to the failed node; Swarm reconciles desired vs actual state continuously.
- docker node update --availability drain worker1 immediately reschedules that node's tasks elsewhere and stops new task placement, used for maintenance; active and pause are the other availability states.
- docker node promote (or docker node update --role manager) turns a worker into a manager; demote reverses it.
- Rolling updates are controlled by --update-parallelism (tasks updated at once), --update-delay (wait between batches), and --update-failure-action (pause, continue, or rollback). Example: docker service update --image myapp:v2 --update-parallelism 2 --update-delay 10s myservice.
- If an update's failure action is set to rollback, a failed task triggers automatic revert to the previous service configuration; --rollback-monitor and --rollback-parallelism tune that behavior.
- Placement constraints filter nodes: docker service create --constraint 'node.labels.storage == ssd' or combinations like node.role == manager. A service stays in pending state if no node satisfies its constraints.
- Each Swarm service gets a Virtual IP (VIP) that load-balances across its healthy tasks; services on the same overlay network resolve each other by service name through Swarm's built-in DNS.
- The routing mesh makes a published service port reachable on every node via the ingress overlay network and IPVS, even nodes running no task for that service.
- Inspect and troubleshoot with docker service ls, docker service ps myservice (per-task state and errors), and docker service logs <service> (aggregated task logs).
Domain 2: Image Creation, Management, and Registry
- Multi-stage builds use multiple FROM statements; each FROM starts a fresh filesystem, and COPY --from=<stage> pulls only needed artifacts into the runtime stage, shrinking final image size by leaving build tooling behind.
- Only instructions that change the filesystem create layers: RUN, COPY, and ADD produce layers; ENV, LABEL, EXPOSE, CMD, ENTRYPOINT, and WORKDIR add metadata without a new filesystem layer.
- ENTRYPOINT in exec form (JSON array) defines the fixed executable and cannot be overridden by docker run arguments; CMD supplies default arguments that ARE overridable, and when both exist CMD values are appended as arguments to ENTRYPOINT.
- Exec form (CMD ["nginx", "-g"]) runs the binary directly as PID 1; shell form (CMD nginx -g) wraps it in /bin/sh -c, which can swallow signals and break graceful shutdown.
- COPY only moves local build-context files; ADD additionally fetches remote URLs and auto-extracts local tar archives. Best practice is to prefer COPY unless you specifically need ADD's extraction.
- Order Dockerfile instructions for cache efficiency: copy the dependency manifest (package.json, requirements.txt, go.mod) and install dependencies BEFORE copying the rest of the source so code changes do not bust the dependency layer.
- .dockerignore excludes files and directories from the build context sent to the daemon, reducing build time, image size, and the risk of leaking secrets.
- docker build -t myapp:abc123 -t myapp:latest . applies multiple tags in one build; pushing without an explicit tag defaults to the latest tag.
- docker image history <image> shows the layers, their sizes, and the instruction that created each, useful for spotting bloat.
- docker image prune removes dangling images (untagged and unreferenced); add -a to also remove unused tagged images. docker system prune cleans containers, networks, and build cache too.
- HEALTHCHECK defines a command Docker runs periodically to mark a container healthy, unhealthy, or starting; Swarm and orchestrators use this status for scheduling and restart decisions.
- Minimize image size with alpine-based images, distroless images, or FROM scratch with a statically compiled binary; combine related RUN commands to reduce layer count.
- Run a local registry with docker run -d -p 5000:5000 --name registry registry:2; secure it with TLS certificates for HTTPS and HTTP basic or token-based authentication.
- Move images between hosts without a registry using docker save -o image.tar myimage to create a tar archive and docker load -i image.tar to restore it.
Domain 3: Installation and Configuration
- The Docker daemon is configured via /etc/docker/daemon.json; common keys include storage-driver, data-root, dns, hosts, and log-driver. The daemon must be restarted (sudo systemctl restart docker) for changes to take effect.
- overlay2 is the recommended and default storage driver on modern kernels; others include devicemapper, btrfs, and zfs. After an engine upgrade, keep daemon.json pinned to the same storage driver used before to avoid losing existing images and containers.
- Set the default storage location with the data-root option (for example {"data-root": "/data/docker"}); the legacy graph key is deprecated. Isolating /var/lib/docker on its own partition/disk is a best practice.
- Configure persistent container DNS by setting the dns key in /etc/docker/daemon.json (for example {"dns": ["8.8.8.8"]}).
- Bind the daemon API to a TCP socket via the hosts key (for example {"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]}); port 2376 is the conventional TLS-secured port. Note hosts in daemon.json can conflict with systemd's -H flag.
- Secure remote daemon access with TLS using three files: the CA certificate (ca.pem), server certificate (server-cert.pem), and server key (server-key.pem), with matching client certs.
- Configure an HTTP/HTTPS proxy for the daemon in a systemd drop-in file at /etc/systemd/system/docker.service.d/http-proxy.conf, then run systemctl daemon-reload and restart Docker.
- Docker supports multiple logging drivers: json-file (default), syslog, journald, fluentd, splunk, gelf, and awslogs; set the default with the log-driver key or per-container with --log-driver.
- Add a non-root user to the docker group, then log out and back in, to run docker commands without sudo; membership effectively grants root-equivalent access to the host.
- Linux namespaces provide isolation: PID (process), NET (network), MNT (filesystem), UTS (hostname), IPC, and USER. Control groups (cgroups) limit and account for CPU, memory, and I/O resource usage per container.
- Verify the engine with docker info (system-wide config, driver, resources) and docker version (client/server versions); both confirm the daemon is running and responsive.
- Enable the daemon to start on boot with sudo systemctl enable docker on systemd-based distributions.
- Live restore ({"live-restore": true}) keeps containers running while the daemon is stopped or upgraded; it is not compatible with Swarm mode.
- Containerd is the default underlying container runtime; the daemon delegates container lifecycle to containerd, which uses runc as the OCI runtime.
Domain 4: Networking
- The built-in network drivers are bridge (default for standalone containers), host, none, overlay (multi-host Swarm), and macvlan; ipvlan is also available.
- User-defined bridge networks provide automatic DNS resolution of containers by name via Docker's embedded DNS at 127.0.0.11; the default bridge (docker0) does NOT, requiring legacy --link instead.
- docker network create mynet defaults to the bridge driver on the local host; add --driver overlay for Swarm-wide networks.
- Publish ports with -p <host-port>:<container-port>; -p 8080:80 forwards host port 8080 to container port 80 via iptables NAT, host port always listed first.
- The host network driver (--network host) removes network isolation: the container shares the host's network namespace, IP, and ports, binding directly to host ports with no NAT.
- The none driver disables all networking, leaving only a loopback interface, useful for fully isolated batch jobs.
- Overlay networks require Swarm mode and use the VXLAN data plane to encapsulate traffic across hosts; create with docker network create --driver overlay --attachable mynet.
- The --attachable flag on an overlay network lets standalone (non-service) containers connect to it alongside Swarm services.
- Connect a running container to an additional network with docker network connect <network> <container>; disconnect with docker network disconnect.
- macvlan assigns containers their own MAC and IP on the physical LAN; by default the host cannot reach its own macvlan containers because the kernel blocks traffic between a parent interface and its macvlan sub-interfaces.
- The Swarm routing mesh, built on the ingress overlay network and IPVS, makes a published service port reachable on every node regardless of where tasks actually run.
- Inspect networks with docker network inspect mynetwork to see driver, subnet, gateway, and attached containers; list with docker network ls.
- Retrieve a container's IP with docker inspect --format '{{.NetworkSettings.IPAddress}}' <container> (or the per-network path for non-default networks).
- In Compose, services on the same custom network reach each other by service name; define an overlay network and attach both services to enable cross-host service discovery.
Domain 5: Security
- Docker Content Trust (DCT) uses The Update Framework (TUF) and Notary to sign image tags at push and verify signatures on pull; enable it by exporting DOCKER_CONTENT_TRUST=1 to enforce signature checks on pull, push, run, and build FROM.
- Swarm secrets are created with docker secret create my_secret ./secret.txt, stored encrypted in the Raft log, delivered to authorized tasks over mutual TLS, and mounted on tmpfs as files under /run/secrets/<name> inside the container (never written to worker disk).
- The --privileged flag grants nearly all Linux capabilities, mounts the host /dev tree, and disables seccomp/AppArmor, effectively breaking container isolation; avoid it in production.
- Drop and add capabilities precisely: docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp follows least privilege; NET_BIND_SERVICE lets a non-root process bind ports below 1024.
- --security-opt no-new-privileges sets the no_new_privs kernel bit, preventing the process from gaining new privileges via setuid binaries or file capabilities.
- Docker applies a default seccomp profile that blocks roughly 44 dangerous syscalls, plus mandatory access control via AppArmor (Ubuntu/Debian) or SELinux (RHEL/CentOS).
- User namespace remapping (userns-remap in daemon.json) maps container root to an unprivileged host UID/GID, so a compromised root inside the container is not root on the host.
- Use the USER instruction in the Dockerfile to run the application as a non-root user, following the principle of least privilege.
- Run containers read-only with --read-only and provide writable scratch space via tmpfs mounts; pin base images to specific digests (image@sha256:...) for reproducible, verifiable builds.
- Use BuildKit secret mounts (RUN --mount=type=secret,id=mysecret ...) to expose secrets only during a build step without baking them into image layers.
- Swarm control-plane traffic is encrypted by default with mutual TLS; overlay data-plane traffic is unencrypted unless you add --opt encrypted to the network (IPSec).
- Swarm node certificates rotate automatically with a default expiry of 90 days; change it with docker swarm update --cert-expiry <duration>.
- Scan images for vulnerabilities before deploying with docker scan (Snyk-based) or docker scout; integrate scanning into CI.
- Reduce attack surface with minimal base images (Alpine or distroless) and by removing build tools, shells, and package managers from the runtime image.
Domain 6: Storage and Volumes
- Docker supports exactly three mount types: volume (Docker-managed under /var/lib/docker/volumes/), bind (any existing host path), and tmpfs (host RAM only).
- Volumes are created and managed by the Docker daemon and survive container removal; bind mounts reference an arbitrary host path that Docker does not manage or clean up.
- Create a named volume with docker volume create myvolume and attach with -v myvolume:/app/data so data persists independently of the container lifecycle.
- Bind-mount a single file or directory for live development or config injection, for example -v /host/path/config.yml:/etc/app/config.yml; append :ro to make any bind or volume mount read-only.
- The modern --mount flag uses explicit key=value pairs (type=volume,source=myvol,target=/data) and is preferred over -v for clarity and better error reporting; type can be volume, bind, or tmpfs.
- tmpfs mounts live entirely in host memory, are never written to disk or the container's writable layer, and disappear when the container stops, making them ideal for sensitive or ephemeral data; cap them with a size limit.
- By default docker rm leaves a container's anonymous volumes behind as orphaned volumes consuming disk; use docker rm -v to remove them, or docker volume prune to clean up dangling volumes.
- When a container is stopped or removed, attached named volumes are preserved and retain their data; they must be removed explicitly with docker volume rm.
- Mount an NFS share as a local-driver volume: docker volume create --driver local --opt type=nfs --opt o=addr=192.168.1.10,rw --opt device=:/data myvolume.
- Volume plugins (REX-Ray, Portworx, NFS-based drivers) extend the volume subsystem through a plugin API to support third-party and networked storage backends.
- Back up and migrate a volume by running a temporary container that mounts it and tars its contents (docker run --rm -v myvol:/data -v $(pwd):/backup alpine tar czf /backup/vol.tar.gz /data), then restore on the target host.
- The overlay2 storage driver manages image layers and the per-container thin writable layer using copy-on-write; this is separate from volumes, which bypass the union filesystem for performance and persistence.
- List, inspect, and remove volumes with docker volume ls, docker volume inspect <name>, and docker volume rm <name>.
- For persistent database storage that must survive container recreation, use a named volume; for sharing source code into a container for live reload during development, use a bind mount.
DCA exam tips
- Memorize quorum math: for N managers, quorum is (N/2)+1, so a 3-manager cluster tolerates 1 failure and a 5-manager cluster tolerates 2. Many orchestration questions hinge on this and on running an odd number of managers across AZs.
- Know the exact flag syntax: -p host:container for ports, -v name:/path versus -v /host:/path for volumes vs bind mounts, and --cap-drop ALL --cap-add <CAP>. The exam tests precise CLI strings, not concepts alone.
- Be able to distinguish near-identical options on multiple-select questions (e.g., COPY vs ADD, replicated vs global services, default bridge vs user-defined bridge DNS). Read every option; several questions have more than one correct answer.
- Drill the daemon.json keys (storage-driver, data-root, dns, hosts, log-driver) and where systemd-specific config lives (drop-in files under /etc/systemd/system/docker.service.d/), since installation/config questions cite exact file paths.
- Manage your 90 minutes across roughly 55 questions: flag long multi-select scenario items, answer the quick command-recall questions first, and leave nothing blank since there is no penalty for guessing.
Study guide FAQ
How many questions are on the DCA and how long do I get?
The exam is 90 minutes and consists of multiple-choice and multiple-select questions, typically around 55 items. You need roughly 65% to pass. Pace yourself at well under two minutes per question and flag the long scenario questions to revisit.
Which domain carries the most weight?
Orchestration (Swarm) is the largest domain, followed closely by Image Creation/Management/Registry and Installation/Configuration. Networking, Security, and Storage round out the rest. Prioritize deep Swarm and image-build knowledge, but do not neglect the smaller domains since the margins are tight.
Does the exam cover Kubernetes?
The classic DCA focuses on Docker Swarm for orchestration, not Kubernetes. You should know Swarm services, stacks, the Raft quorum model, overlay networking, and the routing mesh thoroughly. General container and image concepts transfer to any orchestrator, but Swarm-specific commands are what is tested.
What is the best way to prepare hands-on?
Build a multi-node Swarm (even with VMs or cloud instances), then practice initializing the cluster, deploying stacks from Compose files, performing rolling updates and rollbacks, draining nodes, creating secrets, and wiring up overlay and macvlan networks. Pair that lab work with writing multi-stage Dockerfiles and configuring daemon.json so the command syntax becomes muscle memory.