Chapter 73: DevOps Projects Part 3: Docker Websites, APIs, Compose, Registry and ECR
73.1 Project 17: Containerize a static website
Friends, every company ships a marketing site. Today we put a static HTML site into an nginx Alpine image, run it on port 8080, and prove it with curl. Small image, clear steps.
मित्रांनो, प्रत्येक company marketing site पाठवते. आज static HTML site nginx Alpine image मध्ये टाकू, port 8080, curl ने सिद्ध करू.
दोस्तों, हर company marketing site भेजती है. आज static HTML site nginx Alpine image में डालेंगे, port 8080, curl से सिद्ध करेंगे.
What you will build in this project
- A tiny static site folder.
- A Dockerfile FROM nginx Alpine.
- An image shop-static:1.0.
- A container on host port 8080.
1. Start from a real company story
At Myntra in Bengaluru, the festive landing page was copied by hand onto three EC2 boxes. One box had an old CSS file and the sale banner looked broken on mobile.
Support tickets hit 900 in an hour. Rough brand cost that evening: about ₹12 lakh in lost carts.
Riya packed the site into one nginx image. The same tag ran on every box. Rollback was one previous tag.
Today we build that static site image.
Ravindra Bagale's Tip
Many students use FROM nginx:latest. Pin a version like nginx:1.27-alpine so builds stay repeatable. Keep that habit.
खूप students FROM nginx:latest वापरतात. nginx:1.27-alpine सारखं version pin करा. सवय ठेवा.
बहुत students FROM nginx:latest इस्तेमाल करते हैं. nginx:1.27-alpine जैसा version pin करें. आदत रखिए.
2. Start and prepare
Step 1: Install Docker
Why: We need the engine before any container. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker version confirms install. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 1: version
Type this:
docker version --format '{{.Server.Version}}'
You will see:
27.3.1
What it means: Engine ready.
Example 2: info
Type this:
docker info --format '{{.Driver}}'
You will see:
overlayfs
What it means: Storage driver.
Example 3: hello
Type this:
docker run --rm hello-world 2>&1 | tail -3
You will see:
Hello from Docker!
This message shows that your installation appears to be working correctly.
What it means: OK.
Step 2: Write a tiny site
Why: The site is three static files. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: index.html css and one image path. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 4: mkdir
Type this:
mkdir -p /tmp/static-site && printf '%s\n' '<!doctype html><title>Shop</title><h1>Shop static</h1>' > /tmp/static-site/index.html && cat /tmp/static-site/index.html
You will see:
<!doctype html><title>Shop</title><h1>Shop static</h1>
What it means: Page ready.
Example 5: css
Type this:
printf '%s\n' 'body{font-family:sans-serif}' > /tmp/static-site/style.css && ls /tmp/static-site
You will see:
index.html
style.css
What it means: Assets.
Example 6: link css
Type this:
printf '%s\n' '<!doctype html><title>Shop</title><link rel=stylesheet href=style.css><h1>Shop static</h1>' > /tmp/static-site/index.html && wc -l /tmp/static-site/index.html
You will see:
1 /tmp/static-site/index.html
What it means: Updated.
Step 3: Write the Dockerfile
Why: Dockerfile describes the image. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: FROM nginx alpine and COPY. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 7: Dockerfile
Type this:
printf '%s\n' 'FROM nginx:1.27-alpine' 'COPY index.html /usr/share/nginx/html/index.html' 'COPY style.css /usr/share/nginx/html/style.css' > /tmp/static-site/Dockerfile && cat /tmp/static-site/Dockerfile
You will see:
FROM nginx:1.27-alpine
COPY index.html /usr/share/nginx/html/index.html
COPY style.css /usr/share/nginx/html/style.css
What it means: Pinned tag.
Example 8: dockerignore
Type this:
printf '%s\n' '.git' '*.md' > /tmp/static-site/.dockerignore && cat /tmp/static-site/.dockerignore
You will see:
.git
*.md
What it means: Lean context.
Example 9: ls
Type this:
ls /tmp/static-site
You will see:
Dockerfile
index.html
style.css
.dockerignore
What it means: Ready to build.
3. Build the main pieces
Step 4: Build the image
Why: build creates layers. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker build -t. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 10: build
Type this:
docker build -t shop-static:1.0 /tmp/static-site
You will see:
Successfully tagged shop-static:1.0
What it means: Image built.
Example 11: images
Type this:
docker images shop-static
You will see:
REPOSITORY TAG IMAGE ID CREATED SIZE
shop-static 1.0 a1b2c3d 10 seconds ago 45MB
What it means: Listed.
Example 12: history
Type this:
docker history shop-static:1.0 | head -4
You will see:
IMAGE CREATED CREATED BY SIZE
a1b2c3d ...
What it means: Layers.
Step 5: Run the container
Why: run starts a container. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker run -d. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 13: run
Type this:
docker run -d --name shop-static -p 8080:80 shop-static:1.0 && echo started
You will see:
started
What it means: Detached.
Example 14: ps
Type this:
docker ps --filter name=shop-static --format '{{.Names}} {{.Status}} {{.Ports}}'
You will see:
shop-static Up 2 seconds 0.0.0.0:8080->80/tcp
What it means: Mapped.
Example 15: curl
Type this:
curl -s http://127.0.0.1:8080/ | head -1
You will see:
<!doctype html><title>Shop</title><link rel=stylesheet href=style.css><h1>Shop static</h1>
What it means: Serving.
Step 6: Map port 8080
Why: Host port reaches the site. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: -p 8080:80. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 16: code
Type this:
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/
You will see:
200
What it means: OK.
Example 17: css fetch
Type this:
curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8080/style.css
You will see:
200
What it means: CSS served.
Example 18: headers
Type this:
curl -sI http://127.0.0.1:8080/ | head -3
You will see:
HTTP/1.1 200 OK
Server: nginx
Date: ...
What it means: nginx.
4. Automate and verify
Step 7: Check logs
Why: Logs prove it is serving. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker logs. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 19: logs
Type this:
docker logs shop-static 2>&1 | tail -3
You will see:
GET / HTTP/1.1 200
GET /style.css HTTP/1.1 200
What it means: Access lines.
Example 20: follow note
Type this:
echo 'docker logs -f shop-static'
You will see:
docker logs -f shop-static
What it means: Follow mode.
Example 21: inspect ip
Type this:
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' shop-static
You will see:
172.17.0.2
What it means: Bridge IP.
Step 8: Exec into container
Why: exec is for quick checks. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker exec. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 22: exec
Type this:
docker exec shop-static ls /usr/share/nginx/html
You will see:
index.html
style.css
What it means: Files inside.
Example 23: uname
Type this:
docker exec shop-static uname -a | awk '{print $1,$3}'
You will see:
Linux 6.8.0-1015-aws
What it means: Shared kernel.
Example 24: nginx -v
Type this:
docker exec shop-static nginx -v 2>&1
You will see:
nginx version: nginx/1.27.0
What it means: Pinned.
Step 9: Tag the image
Why: Tags name versions. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker tag. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 25: tag
Type this:
docker tag shop-static:1.0 shop-static:latest && docker images shop-static
You will see:
shop-static 1.0 ...
shop-static latest ...
What it means: Two tags same id.
Example 26: rmi safe
Type this:
echo 'do not rmi while container runs'
You will see:
do not rmi while container runs
What it means: Caution.
Example 27: filter
Type this:
docker images --filter reference=shop-static
You will see:
REPOSITORY TAG ...
What it means: Filtered.
5. Harden and accept
Step 10: Save and load
Why: save moves images offline. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker save then load. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 28: save
Type this:
docker save shop-static:1.0 -o /tmp/shop-static-1.0.tar && ls -lh /tmp/shop-static-1.0.tar
You will see:
-rw-r--r-- 1 user user 45M Oct 28 12:20 /tmp/shop-static-1.0.tar
What it means: Archive.
Example 29: load note
Type this:
echo 'on another host: docker load -i shop-static-1.0.tar'
You will see:
on another host: docker load -i shop-static-1.0.tar
What it means: Offline move.
Example 30: file type
Type this:
file /tmp/shop-static-1.0.tar | head -1
You will see:
/tmp/shop-static-1.0.tar: POSIX tar archive
What it means: Tar.
Step 11: Clean up
Why: Stop leftovers. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: docker rm -f. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 31: stop
Type this:
docker rm -f shop-static && echo removed
You will see:
removed
What it means: Gone.
Example 32: ps empty
Type this:
docker ps -a --filter name=shop-static --format '{{.Names}}' | wc -l
You will see:
0
What it means: Clean.
Example 33: image kept
Type this:
docker images -q shop-static:1.0 | wc -l
You will see:
1
What it means: Image remains.
Step 12: Acceptance checklist
Why: Riya signs off when these pass. We do this before the next step so mistakes stay small and easy to undo. Read the output carefully; the numbers and names tell you if the machine is healthy.
What: All green. Follow the numbered examples below. Type each command, read the exact output, and match the meaning line before you move on. That is how real teams learn a tool.
Example 34: smoke
Type this:
docker run -d --name shop-static-smoke -p 8081:80 shop-static:1.0; curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8081/; echo; docker rm -f shop-static-smoke; echo ok
You will see:
200
ok
What it means: Smoke pass.
Example 35: no 777
Type this:
stat -c '%a' /tmp/static-site/Dockerfile
You will see:
644
What it means: Safe mode.
Example 36: Sign-off
Type this:
echo 'Riya: PASS'
You will see:
Riya: PASS
What it means: Done.
Check yourself
Q1. Base image Riya used?
nginx:1.27-alpine
Q2. Host port in the lab?
8080
Q3. Command to build?
docker build
Q4. Command to run detached?
docker run -d
Q5. Who fixed Myntra page?
Riya
Q6. Why pin the tag?
So builds stay repeatable
Friends, you containerized a static site with a pinned nginx Alpine image. Did you understand? Let us try it once more. Change the h1 text, rebuild with tag 1.1, and switch the container.
मित्रांनो, तुम्ही pinned nginx Alpine ने static site containerize केली. h1 बदलून 1.1 tag ने rebuild करा.
दोस्तों, आपने pinned nginx Alpine से static site containerize की. h1 बदल 1.1 tag से rebuild करें.
Lab: try at home
- Write the static files.
- Write Dockerfile with pinned tag.
- Build shop-static:1.0.
- Run on 8080 and curl.
- Tag 1.1 after a text change.
Recap
- Pin base image tags.
- COPY only what you need.
- -p maps host to container.
- Same image on every host.
- save/load moves images offline.