DCubes
Docker module

Lesson 7

Write a Dockerfile

FROM, COPY, RUN, CMD, docker build, and why you do not bake secrets into an image.

beginner35 minRun on your machine

What you will be able to do

  • Write a small Dockerfile that copies a script and sets CMD
  • Build a tagged image and run it
  • Explain why passwords do not belong in Dockerfile lines

Why this matters for DE and AI

A job image is a Dockerfile: start from a base, copy extract.sh (or later Python), set the command. If the recipe is missing a file, every cluster that pulls the image is missing it too. Building locally is how you find that before a scheduler does.

Concepts

A Dockerfile is a list of instructions. We will use four:

Instruction Meaning
FROM alpine:3.20 Start from this image
WORKDIR /app Create/set the working directory
COPY greet.sh /app/greet.sh Copy from the build context (usually .) into the image
RUN chmod +x /app/greet.sh Run a command at build time (layers the result)
CMD ["/app/greet.sh"] Default command when someone docker runs

CMD vs command on docker run: if you pass a command after the image name, it replaces CMD.

Build context is the directory you pass to docker build. COPY can only see files inside it. That is why we build from a small folder, not from $HOME.

docker build -t dcubes-hello:1 .

-t tags the result. . is the context (the directory with the Dockerfile).

.dockerignore is a list of names not to send in the context (like .gitignore). Optional for this tiny lab; required later when the folder has data files you do not want in the image.

Practice on your machine

mkdir -p ~/dcubes/docker-lab/hello
cd ~/dcubes/docker-lab/hello

Write a script the image will run:

cat > greet.sh << 'EOF'
#!/bin/sh
echo "hello from a dcubes image"
echo "time: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
EOF

Write the Dockerfile (filename has no extension):

cat > Dockerfile << 'EOF'
FROM alpine:3.20
WORKDIR /app
COPY greet.sh /app/greet.sh
RUN chmod +x /app/greet.sh
CMD ["/app/greet.sh"]
EOF

Build:

docker build -t dcubes-hello:1 .

What you should see: steps for FROM, WORKDIR, COPY, RUN, CMD. Docker caches steps; a second build is nearly instant if nothing changed.

docker images dcubes-hello
docker run --rm dcubes-hello:1

What you should see: repository dcubes-hello, tag 1, then two lines of greeting and a UTC timestamp.

Override CMD once, to prove you can:

docker run --rm dcubes-hello:1 cat /app/greet.sh

That prints the script instead of running it.

Change the echo line in greet.sh, rebuild with the same tag, and run again. You should see the new text. Same tag, new image ID — tags move locally too when you rebuild.

Common mistakes

  • Building from the wrong directory. COPY greet.sh fails if you are in docker-lab and the file is in hello/. cd into hello (or pass -f and a context path).
  • Forgetting chmod +x. CMD then fails with permission denied.
  • Using ADD instead of COPY. ADD can extract archives and fetch URLs. Prefer COPY unless you have a reason.

Next

Persist data — bind mounts and named volumes so files survive rm.