DCA study materials
DCA study resources

Docker Certified Associate (DCA) common mistakes

DCA · Understand the traps and how to avoid them.

Mistake 1

Treating `docker service create` and `docker stack deploy` as interchangeable and expecting a stack file to work with `docker service create` or vice versa, then freezing when the CLI rejects flags such as `--replicas` placement syntax or rejects a Compose v3 file because of unsupported keys.

Candidates study Swarm services and Compose stacks as one topic and memorise one set of flags. The two paths differ: stack files (Compose v3) support a limited key set and are deployed with docker stack deploy -c, while docker service create takes CLI flags and cannot consume a stack file. Some stack-file keys (for example build, depends_on, and certain volume driver options) are ignored or rejected in stack mode, which surprises candidates who practised only with docker-compose up.

What to do instead

Practise both paths separately on a local Swarm. Create a service with docker service create --name web --replicas 3 -p 8080:80 nginx, inspect it with docker service ls and docker service ps web, then scale with docker service scale web=5. Separately write a v3 stack file, deploy with docker stack deploy -c stack.yml app, and list tasks with docker stack services app. Deliberately add an unsupported key and read the error so you know which keys stack mode accepts.

Mistake 2

Assuming `docker stack deploy` automatically builds images from a `build:` key in the stack file, then reporting that the deployed service has no image or runs a stale tag.

docker-compose build and docker-compose up --build build locally, which trains candidates to expect building during deploy. In Swarm stack mode the build key is not supported; every service must reference an image that already exists in a registry reachable by the nodes. Candidates who only tested single-host Compose never hit this.

What to do instead

Build and tag the image first (docker build -t registry.example.com/app:1.0 .), push it (docker push registry.example.com/app:1.0), and reference that exact tag in the stack file. Remember that every Swarm node must be able to pull the image, so a locally built image that was never pushed will fail on other nodes. Verify with docker service ps that tasks are running rather than in rejected or no suitable node states.

Mistake 3

Confusing the roles of `docker service logs`, `docker logs`, and `docker service ps` when a task keeps restarting, and reading only the container logs on the manager node.

On a single host, docker logs <container> is the reflex. In Swarm, the container may run on a worker, and the service name is not a container ID. Candidates run docker logs web and get an error, or run docker service logs and see nothing because the task never started (image pull failure or scheduling failure), which only docker service ps reveals.

What to do instead

Use docker service ps <service> first: it shows each task, its node, and the error string (for example No such image or no suitable node). Then use docker service logs <service> for application output, adding --tail and --follow as needed. To inspect a specific task, use the task ID from docker service ps with docker inspect. Know that docker logs works on a container ID on the node where it runs, not on the service name from the manager.

Mistake 4

Writing a Dockerfile that installs packages and copies source in one layer, or that uses `COPY . .` before `RUN npm install`, then failing questions about build cache and image size because the expected layer order is different.

Candidates write Dockerfiles that work but are not cache-optimal. The exam tests understanding of layer caching: each instruction is a layer, and a change invalidates that layer and all later ones. Copying source before dependency installation busts the dependency cache on every code change. Multi-stage builds and .dockerignore are also frequently missed.

What to do instead

Order instructions from least to most frequently changing: base image, system packages, dependency manifest (COPY package.json then RUN npm install), then application source. Use a .dockerignore to keep build context small. Use multi-stage builds (FROM ... AS build then FROM ... AS runtime and COPY --from=build) to keep final images small. Verify with docker build twice, changing only source, and confirm the dependency layer is reported as CACHED.

Mistake 5

Treating `docker-compose` (v1, hyphenated) and `docker compose` (v2 plugin) as identical, and using v1-only behaviour such as `depends_on` guaranteeing startup order or the default network naming, when the exam environment uses the plugin.

Many tutorials predate Compose v2. Candidates memorise docker-compose up -d, docker-compose.yml defaults, and assume depends_on waits for the dependency to be healthy. In v2 the command is docker compose, the project name and network naming changed, and depends_on with condition: service_healthy requires a healthcheck. Version drift causes confusing failures in the exam environment.

What to do instead

Check the installed version early (docker compose version). Use the v2 syntax docker compose up -d, docker compose ps, docker compose down -v. If ordering matters, define a healthcheck on the dependency and use depends_on: {db: {condition: service_healthy}}. Remember depends_on alone only controls start order, not readiness. Know that docker compose down removes containers and networks but keeps named volumes unless -v is given.

Mistake 6

Publishing a container port with `-p` but binding the application inside the container to `127.0.0.1`, then concluding the port mapping is broken when the host cannot reach the service.

Candidates test the app locally where loopback binding works, then containerise it unchanged. Inside a container, 127.0.0.1 is the container's own loopback, not the host or the Docker bridge, so traffic arriving on the container's eth0 is refused. This is a very common operational failure that appears in troubleshooting questions.

What to do instead

Bind the application to 0.0.0.0 (all interfaces) inside the container, for example --host 0.0.0.0 or the framework equivalent, and keep -p hostPort:containerPort on the run command. Verify with docker port <container> and test from the host with curl localhost:<hostPort>. Inside a container, use the container name or service name, not localhost, to reach another container on a user-defined network.

Mistake 7

Assuming data written to a container's writable layer persists across `docker run` invocations, or that `docker rm` keeps the data, and then failing volume and bind-mount questions.

The writable layer is tied to the container lifecycle. Candidates test with a long-running container and never remove it, so data appears to persist. They also confuse anonymous volumes with named volumes and forget that docker run -v /data creates an anonymous volume that is hard to reuse. Bind mounts and volumes have different semantics for host path existence and permissions.

What to do instead

Use named volumes for persistent data (docker volume create appdata, then docker run -v appdata:/var/lib/data ...) and bind mounts for host paths (-v /host/path:/container/path). Know that docker rm deletes the writable layer but not named volumes; docker rm -v removes anonymous volumes. Use docker volume ls, docker volume inspect, and docker volume prune deliberately. Remember that a bind mount to a nonexistent host path is created as a directory by default, which can mask errors.

Mistake 8

Ignoring the difference between the default `bridge` network and user-defined bridge networks, expecting automatic DNS resolution by container name on the default bridge, or expecting `--link` to be current practice.

On the default bridge, containers resolve each other only by IP unless --link is used, and --link is legacy. Candidates who test with IP addresses or --link are surprised when name resolution fails in a user-defined network scenario, or vice versa when they expect name resolution on the default bridge. Network drivers (bridge, overlay, host, macvlan, none) are tested.

What to do instead

Create a user-defined network (docker network create appnet) and attach containers with --network appnet; embedded DNS then resolves container names and network aliases. Use docker network inspect to see attached containers and IPs. Know that overlay networks are for Swarm services across hosts, host removes network isolation, and none disables networking. Avoid --link in new designs.

Mistake 9

Mishandling image tags and registries: relying on `latest` in a Swarm service, forgetting to `docker login` before push, or expecting `docker pull` to update a running service when the tag is unchanged.

Candidates use latest in local practice because it always works on one machine. In Swarm, latest plus --with-registry-auth and image digest behaviour matter: a service will not redeploy if the tag has not changed unless you force it. Private registry pushes fail without docker login, and candidates misread the auth error as a network problem.

What to do instead

Use immutable, specific tags (semantic versions or git SHAs) in services and stack files. Log in with docker login registry.example.com before pushing. To roll a service to a new image with the same tag, use docker service update --image registry.example.com/app:1.0 --force <service>. For private registries in Swarm, pass --with-registry-auth on docker service create or docker stack deploy so worker nodes can pull.

Mistake 10

Skipping `docker system` hygiene commands and misreading disk exhaustion: not knowing that stopped containers, dangling images, unused volumes, and build cache consume space, then failing cleanup or troubleshooting items.

Candidates focus on run/build/deploy and never practise cleanup. Disk exhaustion is a frequent real-world failure and appears in troubleshooting scenarios. Candidates also confuse docker system prune with docker system prune -a --volumes, and do not realise that pruning volumes can destroy data.

What to do instead

Know the inventory commands: docker system df and docker system df -v. Use docker container prune, docker image prune (dangling only) versus docker image prune -a (all unused), docker volume prune, and docker builder prune. Treat docker system prune -a --volumes as destructive and read the confirmation prompt. In a troubleshooting scenario, check docker system df before assuming an application fault.