How To Dockerize a Project
Video: Day 2/40 — How To Dockerize a Project • https://www.youtube.com/watch?v=nfRsPiRGx74 • Duration: ~35 min
Key terms
| Term | Meaning |
|---|---|
| Dockerfile | The build recipe for an image |
| Base image | The FROM image you build on top of |
| Build context | The files sent to the daemon for the build |
| Layer caching | Reuse of unchanged build steps to speed rebuilds |
| .dockerignore | Excludes files from the build context |
| CMD | The default command a container runs |
| ENTRYPOINT | The fixed executable for the container |
| Tag | The name:version label on an image |
Problem & solution
Knowing what a container is doesn't help until you can package your own app into one. Without a repeatable build-and-ship process, turning source code into a portable image and getting it into a registry is ad hoc and error-prone.
Solution: Write a Dockerfile (base image, copy code, install deps, set the start command), then build, tag, and push it to a registry.
The analogy
To ship cargo through a port you never hand over a loose pile of goods; you seal them into one standardized shipping container so any crane and any ship can handle it the same way. What goes inside, and how it is packed, is written on the packing manifest taped to the door, and the sealed box is then stored in a bonded warehouse until a ship needs it. Dockerizing an app is identical: the Dockerfile is the packing manifest that says how to pack your source code into one container image, which you push to an image registry.
Goal
Take a real app (e.g. a Node.js project), write a Dockerfile, build an image, run it, and push it to Docker Hub.
The Dockerize flow (ASCII)
Dockerizing an app is a four-step pipeline: write a Dockerfile, build an image, run a container, then push to a registry.
Common Dockerfile instructions
These are the core instructions you combine to describe how an image is built and run.
FROM base image to start from
WORKDIR set working directory inside the image
COPY/ADD copy files from host into image
RUN execute a command at BUILD time (creates a layer)
ENV set environment variables
EXPOSE document the port the app listens on
CMD default command at RUN time (can be overridden)
ENTRYPOINT fixed command at RUN time (args appended)
Example Dockerfile (Node.js)
A typical Node.js Dockerfile installs dependencies first, then copies the source, to make the most of layer caching.
FROM node:18-alpine
WORKDIR /app
# copy manifests first to leverage layer caching
COPY package*.json ./
RUN npm install
# then copy the rest of the source
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
Why copy package.json first? (layer caching)
Copying manifests before the source means dependency installs are cached and only rerun when dependencies actually change.
Build, run, push
Once the Dockerfile exists, you build the image, run it locally to test, then tag and push it to Docker Hub.
docker build -t myapp:1.0 .
docker run -d -p 3000:3000 --name myapp myapp:1.0
curl localhost:3000
# tag + push to Docker Hub
docker login
docker tag myapp:1.0 <dockerhub-user>/myapp:1.0
docker push <dockerhub-user>/myapp:1.0
.dockerignore (don't ship junk)
A .dockerignore file excludes files from the build context, just like
.gitignore does for git.
node_modules
.git
Dockerfile
*.log
.env
Keeps the build context small and avoids leaking secrets.
CMD vs ENTRYPOINT (ASCII)
CMD sets a default that arguments fully replace, while ENTRYPOINT sets a fixed command that arguments are appended to.
CMD ["node","index.js"] docker run img otherarg
\__ fully replaced by "otherarg"
ENTRYPOINT ["node"] docker run img index.js
\__ "index.js" appended -> node index.js
End-to-end flow
Turning your own app into a published image: write the Dockerfile, build, test locally, tag, then push.
Key takeaways
- Order Dockerfile steps from least- to most-frequently changed for caching.
- Use
.dockerignoreto shrink context & protect secrets. EXPOSEis documentation;-pactually publishes the port.
Checklist
- [ ] Wrote a Dockerfile for a real app
- [ ] Built, ran, and curled it locally
- [ ] Pushed image to Docker Hub
- [ ] Added a
.dockerignore