#4 of Learning DevOps Concepts as a Full Stack Developer: Writing First Dockerfile
Hey folks, it’s Amandeep back at it, still chasing my DevOps dreams as a full stack developer! It’s 07:51 PM IST on Tuesday, September 30…
#4 of Learning DevOps Concepts as a Full Stack Developer: Writing First Dockerfile
Photo by Joshua Reddekopp on Unsplash
Hey folks, it’s Amandeep back at it, still chasing my DevOps dreams as a full stack developer! It’s 07:51 PM IST on Tuesday, September 30, 2025, and I just wrapped up writing my first Dockerfile. This is my fourth article of the journey and I’m spilling the beans on what a Dockerfile is, breaking down its structure in my own words, sharing a Node.js TypeScript backend example I pieced together (including the folder setup I used), and walking you through how I got it running. I’m still learning on the fly here, so join me for the ride — maybe we’ll learn something together!
1. What is a Dockerfile?
Okay, so a Dockerfile? Basically its a set of commands that tells Docker how to whip up a container. It’s just a plain text file where I wrote down what I need — starting with a base image, tossing in my app’s code and dependencies, and laying out the steps to make it work. I gave it a shot today, and it felt like handing Docker a to-do list — kinda cool!
2. Getting the Hang of Dockerfile Structure
Dockerfiles aren’t too tricky once you get the flow, and here’s how I’ve figured it out so far:
- The “FROM” Kickoff: Mostly Every Dockerfile starts with a
FROMline, which is like picking the base flavor—say,FROM node:18to grab the Node.js 18 image. It’s where I start building everything. - The Commands Part: Next, I throw in commands to set things up — stuff like installing dependencies, copying files, and tweaking the setup. Think
RUN,COPY, andWORKDIR—I’ll show these in action soon. - Keeping It Going: Then I add more steps — like opening ports, deciding how to start the app, or setting env variables. It’s like layering ingredients until my “dish” is ready to serve.
It hit me that it’s just a step-by-step guide Docker follows — nothing fancy, just my instructions in order!
# FROM section
Usually here we write a base image, which means what is the minimum we need
over which we are builting our app. For example we need a Node js to run a node application.
# Commands section (Packaging commands)
Here we write commands to Built the image, what are neccessary steps required
to run our project.
# final wrap up command
Usually this command is the final one which is used to execute the container.
3. Example: Node.js Backend with TypeScript
Let’s get real! I threw together a simple Node.js backend with TypeScript and here’s the Dockerfile I hacked out. It’s a basic API, and this is how I boxed it up:
FROM node:18-alpine. # The from part
# set of packaging commands
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build || npx tsc
EXPOSE 3000
# command to execute the container
CMD ["node", "dist/index.js"]
Folder Structure of My Node Project
Here’s how I organized my project folder before building the Dockerfile — kept it simple but functional:
my-node-app/
├── src/
│ └── index.ts # Main TypeScript file with the API logic
├── dist/ # Compiled JavaScript goes here (created after build)
├── node_modules/ # Dependencies installed by npm
├── package.json # Lists dependencies and scripts
├── package-lock.json # Locks dependency versions
└── tsconfig.json # TypeScript config file
└── Dockerfile # The recipe file itself
src/index.tshas my API code (e.g.,app.get('/hello', (req, res) => res.send('Hi from Docker!'))).package.jsonincludes"scripts": { "build": "tsc" }and dependencies like"express"and"typescript".tsconfig.jsonsets up TypeScript (I used a basic setup with"outDir": "dist").- The
distfolder pops up afternpm run buildcompiles the code.
4. How I Got My Dockerfile Running
This was the fun part where I actually saw it come to life! Here’s what I did:
- Build the Image: I popped into my terminal, went to the my-node-app folder, and typed:
docker build -t my-node-app:1.0 .
- The
-t my-node-app:1.0gives it a name, and the dot (.) points to my current spot. you can also use tags to gave versioning to our images. We will explore this in future articles. - Run the Container: Once it built, I fired it up with:
docker run -p 3000:3000 -d my-node-app:1.0
- The
-p 3000:3000links my machine’s port to the container’s, and-dkeeps it running in the background. To check whether containers starts or not you can usedocker ps. it worked in my case. we can also execute it using some cli arguments, we will explore that in future. - Test It Out: I typed
http://localhost:3000/helloin my browser and got “Hi from Docker!” - Clean Up: After playing around, I stopped it with
docker stop <container_id>and deleted it withdocker rm <container_id>to keep things clean.
5. Making Sure Docker Images Run Everywhere
I am doing experiments in both apple silicon chips and intel chips and I created a Docker image on my Intel-chip Mac, pushed it to Docker Hub, and tried running it on a machine with a Silicon (Apple M1) chip. It wouldn’t work — total frustration! The issue? The image was built for an Intel architecture, but the Silicon chip needed an ARM-based one. Here’s how I’m tackling this now:
- Use Multi-Architecture Images: I learned to build images for multiple platforms using docker buildx. I ran:
docker buildx build --platform linux/amd64,linux/arm64 -t my-node-app:1.0 --push .
- This creates an image that works on both Intel and ARM chips. The — push sends it to Docker Hub.
- Check the Base Image: Starting with a multi-arch base like node:18 helps, as it supports various architectures.
- Test Across Machines: I now test my image on different setups (Intel and Silicon) to catch issues early. Pulled it on a friend’s M1 Mac, and it ran like a charm this time!
This step ensures my app isn’t stuck on one machine type — huge relief!
What’s Next?
So overall it was fun and great learning, now as an engineers we first build and there is always a room for improvements/optimizations later, so I will probably spent some more time in exploring best practices and otpmization techniques while writing the docker file and I will share with you in upcoming articles. Got any Dockerfile hacks or silly mistakes you’ve made? Drop them in the comments — I’d love to hear your stories!
메타데이터
- post_id
- 7dfc77361d62
- slug
- 4-of-learning-devops-concepts-as-a-full-stack-developer-writing-first-dockerfile-7dfc77361d62
- url
- https://medium.com/@amanbnl/4-of-learning-devops-concepts-as-a-full-stack-developer-writing-first-dockerfile-7dfc77361d62
- canonical_url
- https://medium.com/@amanbnl/4-of-learning-devops-concepts-as-a-full-stack-developer-writing-first-dockerfile-7dfc77361d62
- author_url
- https://medium.com/@amanbnl
- status
- ok
- fetched_at
- 2026-07-17 03:39:40