DEV Community

Aisalkyn Aidarova
Aisalkyn Aidarova

Posted on

Docker Lab: Run a Simple Website in a Container

Goal

By the end, students will understand:

  • What a Dockerfile is
  • What a Docker image is
  • What a Docker container is
  • How DevOps engineers package and run applications
  • How to expose an application to a browser

Real DevOps Scenario

A developer created a small website.

As a DevOps engineer, your job is to package this website into a Docker image so it can run the same way on:

  • your laptop
  • another developer’s laptop
  • a test server
  • production server
  • Kubernetes later

This solves the common problem:

It works on my machine, but not on the server.
Enter fullscreen mode Exit fullscreen mode

Docker helps us make the environment consistent.


Step 1: Create Project Folder

mkdir docker-website-lab
cd docker-website-lab
Enter fullscreen mode Exit fullscreen mode

Why?

We create one folder for our application files.

This folder will contain:

docker-website-lab
├── index.html
└── Dockerfile
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Simple Website File

touch index.html
Enter fullscreen mode Exit fullscreen mode

Open the file:

nano index.html
Enter fullscreen mode Exit fullscreen mode

Paste this:

<!DOCTYPE html>
<html>
<head>
    <title>Docker Lab</title>
</head>
<body>
    <h1>Hello from Docker!</h1>
    <h2>This website is running inside a container.</h2>
    <p>Created by a DevOps student.</p>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Save:

CTRL + O
ENTER
CTRL + X
Enter fullscreen mode Exit fullscreen mode

Why?

This is our simple application.

In real companies, this could be:

  • React frontend
  • Node.js backend
  • Python API
  • Java application

For beginners, we start with HTML because it is easy to see in the browser.


Step 3: Create a Dockerfile

touch Dockerfile
Enter fullscreen mode Exit fullscreen mode

Open it:

nano Dockerfile
Enter fullscreen mode Exit fullscreen mode

Paste this:

FROM nginx:latest

COPY index.html /usr/share/nginx/html/index.html

EXPOSE 80
Enter fullscreen mode Exit fullscreen mode

Save:

CTRL + O
ENTER
CTRL + X
Enter fullscreen mode Exit fullscreen mode

Step 4: Understand the Dockerfile

Line 1

FROM nginx:latest
Enter fullscreen mode Exit fullscreen mode

Meaning

We are using an existing Nginx image.

Nginx is a web server.

A web server is responsible for showing websites in the browser.

Why DevOps engineers use this

Instead of installing Nginx manually on every server, we use a ready-made Docker image.

Without Docker:

Install Linux
Install Nginx
Configure Nginx
Copy website files
Start Nginx
Fix errors
Enter fullscreen mode Exit fullscreen mode

With Docker:

Use nginx image
Copy website
Run container
Enter fullscreen mode Exit fullscreen mode

Line 2

COPY index.html /usr/share/nginx/html/index.html
Enter fullscreen mode Exit fullscreen mode

Meaning

Docker copies our website file into the Nginx web folder.

Nginx serves files from:

/usr/share/nginx/html/
Enter fullscreen mode Exit fullscreen mode

Why DevOps engineers do this

The application must be inside the image.

When we move the image to another machine, the website goes with it.


Line 3

EXPOSE 80
Enter fullscreen mode Exit fullscreen mode

Meaning

The container will listen on port 80.

Port 80 is the default HTTP web port.

Important

EXPOSE 80 does not publish the port to your laptop automatically.

It only documents that the application inside the container uses port 80.

We still need -p when running the container.


Step 5: Check Files

ls
Enter fullscreen mode Exit fullscreen mode

Expected result:

Dockerfile  index.html
Enter fullscreen mode Exit fullscreen mode

Why?

Before building the image, we must make sure Dockerfile and application files are in the same folder.


Step 6: Build Docker Image

docker build -t student-website:v1 .
Enter fullscreen mode Exit fullscreen mode

Meaning

docker build
Enter fullscreen mode Exit fullscreen mode

Build a Docker image.

-t student-website:v1
Enter fullscreen mode Exit fullscreen mode

Give the image a name and version.

.
Enter fullscreen mode Exit fullscreen mode

Use the current folder as the build context.

Docker will look for the Dockerfile in this folder.


Why DevOps engineers do this

In real DevOps work, we build Docker images after developers push code to GitHub.

Example CI/CD pipeline:

Developer pushes code
↓
GitHub Actions/Jenkins starts
↓
Docker image is built
↓
Image is tested
↓
Image is pushed to ECR/Docker Hub
↓
Application is deployed
Enter fullscreen mode Exit fullscreen mode

Expected Result

You should see something like:

Successfully built ...
Successfully tagged student-website:v1
Enter fullscreen mode Exit fullscreen mode

Step 7: Check Docker Images

docker images
Enter fullscreen mode Exit fullscreen mode

Expected result:

REPOSITORY          TAG
student-website    v1
nginx              latest
Enter fullscreen mode Exit fullscreen mode

What happened?

Docker created an image named:

student-website:v1
Enter fullscreen mode Exit fullscreen mode

The image contains:

  • Nginx
  • Your index.html
  • Configuration needed to run the website

Step 8: Run Container

docker run -d -p 8080:80 --name my-website student-website:v1
Enter fullscreen mode Exit fullscreen mode

Explain the command

docker run
Enter fullscreen mode Exit fullscreen mode

Create and start a container.

-d
Enter fullscreen mode Exit fullscreen mode

Detached mode. Run in the background.

-p 8080:80
Enter fullscreen mode Exit fullscreen mode

Port mapping.

8080
Enter fullscreen mode Exit fullscreen mode

Port on your laptop.

80
Enter fullscreen mode Exit fullscreen mode

Port inside the container.

--name my-website
Enter fullscreen mode Exit fullscreen mode

Name the container.

student-website:v1
Enter fullscreen mode Exit fullscreen mode

Image used to create the container.


Very Important Port Explanation

Container has its own private network.

Nginx runs inside the container on port 80.

Your laptop browser cannot directly access container port 80 unless we publish it.

That is why we use:

-p 8080:80
Enter fullscreen mode Exit fullscreen mode

Meaning:

Browser on laptop
http://localhost:8080
        ↓
Docker forwards traffic
        ↓
Container port 80
        ↓
Nginx
        ↓
index.html
Enter fullscreen mode Exit fullscreen mode

Step 9: Check Running Container

docker ps
Enter fullscreen mode Exit fullscreen mode

Expected result:

CONTAINER ID   IMAGE                PORTS
abc123         student-website:v1   0.0.0.0:8080->80/tcp
Enter fullscreen mode Exit fullscreen mode

Meaning

The container is running.

Port 8080 on your computer is connected to port 80 inside the container.


Step 10: Open Website

Open browser:

http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Expected result:

Hello from Docker!
This website is running inside a container.
Created by a DevOps student.
Enter fullscreen mode Exit fullscreen mode

What did we achieve?

We packaged and ran a website inside Docker.

The website is not running directly on your laptop.

It is running inside a container.


Step 11: View Container Logs

docker logs my-website
Enter fullscreen mode Exit fullscreen mode

Why?

DevOps engineers check logs to troubleshoot applications.

When something is not working, logs help answer:

  • Did the app start?
  • Did users send requests?
  • Are there errors?
  • Is the app crashing?

When you refresh the browser, logs should show HTTP requests.


Step 12: Enter the Container

docker exec -it my-website bash
Enter fullscreen mode Exit fullscreen mode

Now you are inside the container.

Run:

pwd
Enter fullscreen mode Exit fullscreen mode
ls
Enter fullscreen mode Exit fullscreen mode
cd /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode
ls
Enter fullscreen mode Exit fullscreen mode
cat index.html
Enter fullscreen mode Exit fullscreen mode

Exit:

exit
Enter fullscreen mode Exit fullscreen mode

Why?

DevOps engineers sometimes enter containers to troubleshoot.

For example:

  • check files
  • check environment variables
  • check running processes
  • check configuration

But in production, we avoid changing things manually inside containers.

Containers should be recreated from images.


Step 13: Stop Container

docker stop my-website
Enter fullscreen mode Exit fullscreen mode

Check:

docker ps
Enter fullscreen mode Exit fullscreen mode

Expected result:

No running container named my-website
Enter fullscreen mode Exit fullscreen mode

But if you run:

docker ps -a
Enter fullscreen mode Exit fullscreen mode

You will still see it.

Meaning

docker stop stops the container, but does not delete it.


Step 14: Start Container Again

docker start my-website
Enter fullscreen mode Exit fullscreen mode

Check:

docker ps
Enter fullscreen mode Exit fullscreen mode

Open again:

http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Meaning

The same stopped container can be started again.


Step 15: Remove Container

docker rm -f my-website
Enter fullscreen mode Exit fullscreen mode

Meaning

This deletes the container.

The image still exists.

Check:

docker images
Enter fullscreen mode Exit fullscreen mode

You should still see:

student-website   v1
Enter fullscreen mode Exit fullscreen mode

Step 16: Run Again from Same Image

docker run -d -p 8080:80 --name my-website student-website:v1
Enter fullscreen mode Exit fullscreen mode

Important Lesson

Even after deleting the container, we can create a new container from the same image.

Image = template
Container = running instance
Enter fullscreen mode Exit fullscreen mode

Example:

One image
↓
Many containers
Enter fullscreen mode Exit fullscreen mode

Step 17: Make a Change to Website

Open index.html again:

nano index.html
Enter fullscreen mode Exit fullscreen mode

Change this line:

<h1>Hello from Docker!</h1>
Enter fullscreen mode Exit fullscreen mode

to:

<h1>Hello from Docker Version 2!</h1>
Enter fullscreen mode Exit fullscreen mode

Save.


Step 18: Rebuild Image as Version 2

docker build -t student-website:v2 .
Enter fullscreen mode Exit fullscreen mode

Check images:

docker images
Enter fullscreen mode Exit fullscreen mode

Expected:

student-website   v1
student-website   v2
Enter fullscreen mode Exit fullscreen mode

Why?

In real DevOps, every code change should create a new image version.

Examples:

payment-service:v1
payment-service:v2
payment-service:v3
Enter fullscreen mode Exit fullscreen mode

This helps with:

  • deployments
  • rollbacks
  • release tracking
  • troubleshooting

Step 19: Replace Running Container with New Version

Stop and remove old container:

docker rm -f my-website
Enter fullscreen mode Exit fullscreen mode

Run version 2:

docker run -d -p 8080:80 --name my-website student-website:v2
Enter fullscreen mode Exit fullscreen mode

Open:

http://localhost:8080
Enter fullscreen mode Exit fullscreen mode

Expected result:

Hello from Docker Version 2!
Enter fullscreen mode Exit fullscreen mode

Step 20: Clean Up

docker rm -f my-website
Enter fullscreen mode Exit fullscreen mode
docker rmi student-website:v1
Enter fullscreen mode Exit fullscreen mode
docker rmi student-website:v2
Enter fullscreen mode Exit fullscreen mode

Optional:

docker rmi nginx:latest
Enter fullscreen mode Exit fullscreen mode

Final Explanation for Students

Today you acted like a DevOps engineer.

You did this workflow:

Created application file
↓
Created Dockerfile
↓
Built Docker image
↓
Ran container
↓
Opened application in browser
↓
Checked logs
↓
Entered container
↓
Stopped and started container
↓
Created new version
↓
Redeployed new version
Enter fullscreen mode Exit fullscreen mode

Key Concepts

Dockerfile

A recipe that tells Docker how to build an image.

Image

A packaged application with everything needed to run.

Container

A running instance of an image.

Port Mapping

Connects your computer port to the container port.

localhost:8080 → container:80
Enter fullscreen mode Exit fullscreen mode

DevOps Purpose

DevOps engineers use Docker to make applications:

  • portable
  • repeatable
  • consistent
  • easy to deploy
  • easy to scale
  • easier to run in Kubernetes later

Top comments (0)