Run, Manage, and Explore Containers
Run Nginx in Docker, map ports, and serve custom content via bind mounts.
Introduction
30 Second Summary
Every app you deploy in a DevOps role runs inside a container. Knowing your way around Docker's command line is one of the most tested skills in DevOps and SRE interviews.
In this project, you will spin up, manage, and debug Docker containers using real-world images. You will finish with an Nginx web server running in a container, serving a custom HTML page from your machine.
What You'll Build
You will manage the full Docker container lifecycle on Linux, from pulling images to serving custom web content through bind mounts.
By the end of this project, you'll have:
- A running Nginx container serving custom content through port mapping.
- Hands-on experience with 15+ essential Docker CLI commands for managing containers.
- A custom HTML page served from your host into a container via a bind mount.
- A custom bridge network connecting two containers that discover each other by name using DNS.
Are there any prerequisites?
This is Part 1 of the 5-part Docker Mastery Series. You need a Linux system with Docker Engine already installed and basic familiarity with the terminal.
Before We Start
Before We Start...
Verify Your Docker Setup
Before you run any containers, you need to confirm that Docker Engine is installed and running on your Linux system.
You'll verify your installation and set up non-root Docker access. Along the way, you'll see the image-to-container lifecycle in action for the first time.
In this step, get ready to:
- Verify Docker Engine is running and check your version.
- Run your first container without sudo.
- Explore the image-to-container lifecycle.
Verify Docker Engine is running
Docker Engine runs as a background service called a daemon. Before running any containers, you need to confirm the daemon is active and responding to commands.
- Check your Docker installation by running this command:
docker version
You should see version information for both the Client and Server sections. The Server section confirms the Docker daemon is running.
- Get a broader view of your Docker environment by running:
docker info
What do these commands tell you?
- `docker version` shows the version numbers for both the Docker client (CLI) and the server (daemon). If the Server section is missing, the daemon is not running.
- `docker info` shows system-wide details like the number of containers, images, and the storage driver in use.
- Confirm the Docker service itself is active by running:
sudo systemctl status docker
I see active (running)
Your Docker daemon is up and ready. Move on to the next substep.
I see inactive or dead
- Start the Docker service by running:
sudo systemctl start docker
- Verify it is now active by running:
sudo systemctl status docker
You should now see active (running) in the output.
Still not starting?
Check for error details by running sudo journalctl -u docker. This shows the Docker daemon's logs and often reveals the root cause (disk full, conflicting services, etc.).
Help me troubleshoot why my Docker daemon won't start on Linux
Ensure you can run Docker without sudo
Running Docker commands with sudo every time is tedious and unnecessary for development work. Your Linux user needs to be in the docker group to interact with the Docker daemon directly.
- Test non-root access by running this command without sudo:
docker run hello-world
I see Hello from Docker
Your user has the correct permissions. Docker pulled the hello-world image and ran it successfully.
Permission denied
Your user is not in the docker group yet. You need to add yourself to the group so Docker commands work without sudo.
- Add your user to the docker group by running:
sudo usermod -aG docker $USER
- Apply the group change without logging out by running:
newgrp docker
- Verify your access by running docker run hello-world again:
docker run hello-world
You should now see the "Hello from Docker!" message.
Still getting permission denied?
The newgrp command only applies the group change to your current terminal session. If you open a new terminal window, you may need to log out and log back in for the change to take effect everywhere.
Help me fix Docker permission denied errors on Linux
Explore what hello-world just did
That hello-world command did more than print a message. It demonstrated the core Docker workflow: pull an image, create a container from it, run it, and then the container exits.
- See the image that Docker pulled by running:
docker images
You should see hello-world listed with its tag, image ID, and size.
- See the container that ran and has since stopped by running:
docker ps -a
The -a flag shows all containers, including stopped ones. Without it, docker ps only shows running containers.
What is the image-to-container lifecycle?
An image is a read-only template. Think of it as a blueprint for a container.
A container is a running instance created from that image. When you ran docker run hello-world, Docker pulled the hello-world image from Docker Hub, created a container from it, ran the container's default command, and then the container exited.
The stopped container still exists on your system until you explicitly remove it. That is exactly what you are seeing in the docker ps -a output.
Your Docker environment is verified and ready to go. Next up, you'll pull a real-world web server image and get it serving traffic with port mapping.
Pull Images and Run Your First Web Server
Your Docker Engine is verified. In Step 1, hello-world gave you a first look at pulling an image and running a container.
In this step, you'll pull an Nginx web server image and run it as a live container. You'll use port mapping to access the web server directly from your terminal.
In this step, get ready to:
- Pull the Nginx image and explore its metadata.
- Run Nginx as a container with port mapping.
- Understand the key flags for running containers.
Pull the Nginx image and understand image layers
Docker images are the blueprints for containers. You need to pull an image before you can run a container from it.
Why nginx:1.27-alpine?
- Nginx is one of the most common web servers in DevOps and SRE work. It gives you immediate visual feedback through its welcome page, which makes it perfect for learning port mapping.
- The Alpine variant is under 6 MB, making it fast to download.
- Pinning the version (1.27) instead of using :latest is a best practice. In production, :latest can change unexpectedly between pulls.
- Pull the Nginx Alpine image by running this command:
docker pull nginx:1.27-alpine
Watch your terminal as Docker downloads each layer. Each line represents a separate layer of the image.
- Confirm the image was downloaded by running:
docker images
You should see nginx listed with the tag 1.27-alpine, along with its image ID and size.
Pull failed?
- Check your internet connection. Docker needs network access to pull images from Docker Hub.
- Verify Docker is running by running docker info. If you see an error, start Docker with sudo systemctl start docker.
- Why can't I pull the nginx:1.27-alpine image?
- Explore the image's full metadata by running:
docker image inspect nginx:1.27-alpine
What are image layers?
The inspect output shows the internal structure of the image. Here are the key parts to look for:
- Layers are stacked changes that make up the image. Each layer represents an action like installing a package or copying a file. Docker shares layers between images to save disk space.
- Architecture tells you what CPU type the image was built for (e.g. amd64).
- Cmd shows the default command the container runs when it starts. For Nginx, this launches the web server process.
Run Nginx in detached mode with port mapping
An image on its own doesn't do anything. To use it, you create a running container from it.
- Start an Nginx container with port mapping by running this command:
docker run -d --name my-nginx -p 8080:80 nginx:1.27-alpine
- Verify the container is running by running:
docker ps
You should see my-nginx listed with a status of Up.
- Access your web server by running:
curl http://localhost:8080
You should see HTML output containing the default Nginx welcome page. Look for the text Welcome to nginx! in the response.
Not seeing the welcome page?
- Check that port 8080 is not already in use by another process. Run docker ps to see if another container is using port 8080.
- Make sure the container is actually running. If docker ps shows nothing, check docker ps -a to see if the container exited with an error.
- If you see Conflict. The container name "/my-nginx" is already in use, remove the old container first with docker rm -f my-nginx and try the docker run command again.
- Why can't I access my Nginx container on port 8080?
Understand what just happened
You just ran a single command with three important flags. Each one controls a different aspect of how the container runs.
What do -d, -p, and --name do?
- -d (detach) runs the container in the background. Without it, your terminal would be locked to the container's output and you couldn't type any other commands.
- -p 8080:80 creates a port mapping. Traffic hitting port 8080 on your Linux host gets forwarded to port 80 inside the container. The format is always HOST:CONTAINER.
- --name my-nginx gives the container a human-readable name. Without it, Docker assigns a random name like quirky_lovelace.
These three flags are the ones you'll use most often when working with Docker in real DevOps environments.
Your first web server is running inside a Docker container. Next up, you'll learn to manage the container lifecycle by stopping, starting, and removing containers.
Master the Container Lifecycle
Your Nginx container is running and serving the default welcome page on port 8080.
But what happens when you need to stop it, clean it up, or bring it back after maintenance? In this step, you will master the Docker container lifecycle commands that DevOps interviewers test most often.
In this step, get ready to:
- Stop, start, and restart a running container.
- Remove stopped containers to free up disk space.
- Use the --rm flag for automatic container cleanup.
Stop, start, and restart your container
Docker containers are not all-or-nothing. You can stop a container, bring it back, and even restart it without losing any data inside it.
- Stop your my-nginx container by running this command:
docker stop my-nginx
What happens when Docker stops a container?
- Docker sends a SIGTERM signal to the container's main process, giving it a chance to shut down gracefully.
- It waits 10 seconds for the process to finish.
- If the process is still running after 10 seconds, Docker sends SIGKILL to force it down.
- This graceful shutdown behavior is a common Docker interview question.
- Confirm the container is no longer running:
docker ps
Your my-nginx container has disappeared from this list. But it is not deleted.
- Check for stopped containers by running:
docker ps -a
You can see my-nginx still listed with a status of Exited. The container and its filesystem still exist on disk, just in a stopped state.
- Bring the container back to life by running:
docker start my-nginx
- Verify it is running again:
docker ps
- Confirm Nginx is serving content again by running:
curl http://localhost:8080
You should see the default Nginx welcome page HTML in your terminal output. The container picked up right where it left off.
- Try the restart shortcut, which stops and starts in one command:
docker restart my-nginx
What does docker restart do?
It follows the same SIGTERM-then-SIGKILL shutdown process as docker stop, then immediately starts the container again. It is useful when you need a quick bounce after a configuration change.
Container not starting back up?
- Make sure you are using the exact container name. Container names are case-sensitive, so my-nginx is not the same as My-Nginx.
- Run docker ps -a to check if the container still exists. If you accidentally removed it, you will need to create a new one with docker run.
- If another container is already using port 8080, you will see a port conflict. Stop the conflicting container first.
- Help me debug why my Docker container won't start.
Remove containers and understand cleanup
Stopped containers still take up disk space. In production environments, leftover containers accumulate quickly if you do not clean them up.
- Stop the running container first:
docker stop my-nginx
- Remove the stopped container by running:
docker rm my-nginx
Why two separate commands?
By default, docker rm only works on stopped containers. You need to stop it first with docker stop, then remove it with docker rm.
To skip the stop step, you can use docker rm -f to force-remove a running container in one command. The two-command approach is safer for production because it gives the container time to shut down gracefully.
- Confirm the container is gone by running:
docker ps -a
The my-nginx container no longer appears in the list.
- Clean up the hello-world container from Step 1. Find its container ID by running:
docker ps -a
- Copy the container ID for the hello-world entry, then remove it by running:
docker rm [[CONTAINER_ID="your hello-world container ID"]]
- Run docker ps -a one more time to confirm both containers are gone.
docker ps -a
You should only see the nginx:1.27-alpine image listed under docker images now. The containers are gone, but the image remains on disk for future use.
Seeing 'container is running' when trying to remove?
- You need to stop the container before removing it. Run docker stop followed by the container name or ID, then try docker rm again.
- Alternatively, use docker rm -f to force-remove a running container in one step.
- Help me remove a Docker container that won't go away.
Run a container with auto-cleanup
Every container you stop without removing stays on disk. For temporary or test containers, Docker offers the --rm flag to handle cleanup automatically.
- Run a temporary Nginx container with auto-cleanup enabled:
docker run --rm -d --name temp-nginx -p 8080:80 nginx:1.27-alpine
What does --rm do?
- The --rm flag tells Docker to automatically delete the container's filesystem the moment it stops.
- This prevents stopped containers from piling up on your system.
- It is especially useful for quick tests, one-off commands, and CI/CD pipelines where you do not need the container after it finishes.
- Verify the container is running:
docker ps
You should see temp-nginx listed as a running container.
- Now stop the container by running:
docker stop temp-nginx
- Check if the container still exists:
docker ps -a
Notice that temp-nginx does not appear anywhere in the output. Docker removed it the moment it stopped. No manual cleanup needed.
Still seeing temp-nginx in docker ps -a?
- Double-check that you included the --rm flag when you ran the container. Without it, the container stays in stopped state.
- If you forgot --rm, remove the container manually with docker rm temp-nginx and try the command again.
- Help me figure out why my container was not auto-removed.
Your containers are under control. Next up, you will learn how to debug and inspect running containers using logs, exec, inspect, and stats.
Debug and Inspect Running Containers
You now have full control over the container lifecycle. You can start, stop, restart, and remove Docker containers confidently.
The next challenge is figuring out what's happening inside a running container. In this step, you'll use Docker's built-in debugging tools to read logs, open shells, and inspect container internals.
In this step, get ready to:
- Read and follow container logs in real time.
- Open an interactive shell inside a running container.
- Inspect container configuration and monitor resource usage.
Read container logs
When a container misbehaves, logs are the first place to look. Docker captures everything a container writes to standard output and standard error.
- Start a fresh Nginx container by running this command:
docker run -d --name my-nginx -p 8080:80 nginx:1.27-alpine
- Confirm the container is running:
docker ps
You should see my-nginx listed with a status of Up and port 0.0.0.0:8080->80/tcp in the ports column.
Container failed to start?
- If you see a name conflict error, the my-nginx container from a previous step still exists. Remove it with docker rm -f my-nginx and try the run command again.
- If port 8080 is already in use, another process is occupying that port. Stop the other process first, then try again.
- Why won't my Docker container start?
- Generate some traffic by sending a few requests to your Nginx container:
curl http://localhost:8080
curl http://localhost:8080
curl http://localhost:8080
Each command returns the default Nginx welcome page HTML. This is expected.
- View the container's logs by running:
docker logs my-nginx
What do the logs show?
Each line is an Nginx access log entry. You'll see the request method, URL path, HTTP response code, and user agent for each curl request you sent. These are the same logs you'd see if Nginx were running directly on your host.
- Follow the logs in real time by adding the -f flag:
docker logs -f my-nginx
This keeps the log stream open, printing new entries as they arrive. Press Ctrl+C to stop following.
- View only the last 5 log lines by running:
docker logs --tail 5 my-nginx
When should I use each logs option?
- docker logs shows the full log history. Use this to investigate past events.
- docker logs -f follows logs in real time. Use this to watch live traffic or debug startup issues.
- docker logs --tail N shows only the last N lines. Use this to check recent activity without scrolling through old output.
Exec into a running container
Sometimes logs aren't enough. You need to get inside the container and look around. Docker's exec command lets you run a new process inside a running container.
- Open an interactive shell inside your Nginx container by running:
docker exec -it my-nginx sh
What do the -i and -t flags mean?
- -i keeps standard input open so you can type commands.
- -t allocates a pseudo-terminal so the shell behaves like a normal terminal session.
- sh is the shell program to run. Alpine-based images use sh instead of bash.
Your terminal prompt changes to something like / #. You are now inside the container's filesystem.
- Explore the default Nginx files by running:
ls /usr/share/nginx/html/
You should see 50x.html and index.html. These are the default pages Nginx serves.
- View the Nginx configuration file by running:
cat /etc/nginx/nginx.conf
This is the main Nginx config that controls how the web server behaves. You'll see sections for worker processes, event handling, and HTTP settings.
- Check which user you are running as inside the container:
whoami
You should see root. Inside this container, your shell session is running as the root user.
- Type exit to leave the container shell:
exit
Your prompt returns to your normal host terminal. The container keeps running after you exit.
What is the difference between exec and attach?
- docker exec runs a NEW process inside the container. Exiting has no effect on the container itself.
- docker attach connects to the container's EXISTING main process. Pressing Ctrl+C can accidentally stop the container.
- For debugging, exec is almost always what you want.
Got kicked out of the container?
- If the shell exited immediately, make sure you included both -i and -t flags. Without them, the shell has no input stream or terminal to attach to.
- Verify the container is still running with docker ps. If it stopped, restart it with docker start my-nginx and try the exec command again.
- Help me debug why docker exec isn't working on my container.
Inspect and monitor containers
Docker stores detailed metadata about every container. The inspect command exposes all of this as JSON, giving you access to networking details, volume mounts, environment variables, and more.
- View the full configuration of your container by running:
docker inspect my-nginx
What does docker inspect show?
The output is a large JSON document containing everything Docker knows about this container. It includes the container's IP address, port mappings, mounted volumes, environment variables, restart policy, and more.
In production, you'll use this to debug networking issues and verify that a container was launched with the correct configuration.
Scrolling through the full output is useful for exploration. In practice, you'll want to extract specific fields.
- Extract just the container's IP address using the --format flag:
docker inspect --format '{{.NetworkSettings.IPAddress}}' my-nginx
You should see a single IP address printed. This is the container's private IP on the Docker bridge network.
What is the --format flag?
The --format flag uses Go templates to extract specific fields from the JSON output. This is far more precise than piping the full output through grep. You'll see this pattern frequently in Docker and Kubernetes tooling.
- Monitor real-time resource usage by running:
docker stats my-nginx
This shows live CPU, memory, network I/O, and disk I/O statistics for your container. Press Ctrl+C to exit.
- View the processes running inside the container:
docker top my-nginx
What does docker top show?
docker top lists the processes running inside the container, similar to the Linux top command. For Nginx, you'll see a master process and one or more worker processes. This is useful for verifying that the expected processes are running inside a container.
Not seeing an IP address from docker inspect?
- Some Docker network configurations return an empty IP address. Verify the container is running with docker ps first.
- If the IP field is empty, try searching the full inspect output instead:
docker inspect my-nginx | grep IPAddress
Why is docker inspect showing an empty IP address for my container?
You can now debug any container using logs, exec, inspect, and stats. Next up, you'll serve your own custom content by mounting files from your host machine into a container using bind mounts.
Serve Custom Content with Bind Mounts
In Step 4, you learned how to debug and inspect running containers using logs, exec, inspect, and stats. You can now look inside any container and understand exactly what it is doing.
Your Nginx container is still serving the default welcome page. In this step, you will mount your own HTML files into the container using a bind mount so that Nginx serves your custom content instead.
In this step, get ready to:
- Create a project directory and a custom HTML page.
- Mount your host directory into the container with a bind mount.
- Edit content live on your host and see changes instantly in the container.
Create a project directory and custom HTML page
Before you can serve custom content, you need a place on your host machine to store the files. You will create a dedicated directory and write a simple HTML page inside it.
- Create a working directory for your Docker lab files by running this command:
mkdir -p ~/docker-lab/html
- Confirm the directory was created by running:
ls ~/docker-lab
You should see html listed in the output.
- Create a custom HTML page by opening a new file in nano:
nano ~/docker-lab/html/index.html
What is Nano?
Nano is a terminal-based text editor. When you run the command above, your terminal turns into a text editor where you type directly. To save, press Ctrl+O then Enter. To exit, press Ctrl+X.
- Type this HTML content into the Nano editor:
<!DOCTYPE html>
<html>
<head>
<title>Docker Lab</title>
</head>
<body>
<!-- Custom content served from your host machine -->
<h1>Hello from Docker!</h1>
<p>I am learning Docker containers and bind mounts.</p>
</body>
</html>
What does this HTML do?
- The <h1> tag creates a large heading that you will see when you load the page.
- The <p> tag adds a paragraph of body text below the heading.
- This page replaces the default Nginx welcome page that you have been seeing in previous steps.
- Press Ctrl+O, then press Enter to save the file.
- Press Ctrl+X to exit Nano.
- Verify your file was saved correctly by running:
cat ~/docker-lab/html/index.html
You should see the full HTML content you just typed, starting with <!DOCTYPE html> and ending with </html>.
File is empty or missing?
- Make sure you pressed Ctrl+O and then Enter before pressing Ctrl+X. If you exit without saving, your changes are lost.
- Check that you typed the path correctly. Run ls ~/docker-lab/html/ and confirm you see index.html listed.
- If the file is missing, run the nano command again and re-enter the HTML content. Help me troubleshoot my Nano file creation.
Awesome, I've got everything!
Double check you have saved your index.html file before moving on.
I'd like to double check the full code
<!DOCTYPE html>
<html>
<head>
<title>Docker Lab</title>
</head>
<body>
<!-- Custom content served from your host machine -->
<h1>Hello from Docker!</h1>
<p>I am learning Docker containers and bind mounts.</p>
</body>
</html>
Mount your local directory into the container
A bind mount maps a directory on your host machine directly into a container. Whatever files are on your host appear inside the container at the path you specify.
- Remove the existing my-nginx container by running this command:
docker rm -f my-nginx
- Run a new Nginx container with a bind mount by running this command:
docker run -d --name my-nginx -p 8080:80 -v ~/docker-lab/html:/usr/share/nginx/html:ro nginx:1.27-alpine
What do the flags in this command do?
- -v ~/docker-lab/html:/usr/share/nginx/html:ro creates the bind mount. The format is HOST_PATH:CONTAINER_PATH:OPTIONS.
- ~/docker-lab/html is the directory on your host that contains your custom index.html.
- /usr/share/nginx/html is where Nginx looks for web files inside the container. Your host files replace whatever was there before.
- :ro makes the mount read-only inside the container. The container can read your files but cannot modify them. This is a security best practice.
- Verify the container is running with docker ps.
- Test that your custom page is being served by running:
curl http://localhost:8080
You should see your custom HTML in the output, including <h1>Hello from Docker!</h1>. The default Nginx welcome page is gone.
Still seeing the default Nginx page?
- Make sure you removed the old container first. Run docker ps -a and check that only one my-nginx container exists.
- Verify the host path is correct. Run ls ~/docker-lab/html/ and confirm index.html is listed. If the path is wrong, the bind mount creates an empty directory inside the container.
- Check the container's mount with docker inspect my-nginx and look for the Mounts section to verify the source and destination paths. Help me debug my bind mount.
Why use :ro on bind mounts?
The :ro (read-only) flag prevents the container from writing to your host directory. If a container is compromised, it cannot modify your files. In production SRE work, read-only mounts are a standard security practice for any content the container only needs to read.
Edit content live and see changes instantly
The real power of bind mounts shows up during development. Because the container reads directly from your host filesystem, any changes you make to the files on your host appear inside the container immediately.
- Open your HTML file again in Nano by running:
nano ~/docker-lab/html/index.html
- Find this line in the file:
<h1>Hello from Docker!</h1>
- Replace that line with a new heading, so it looks like this:
<h1>Hello from a Bind Mount!</h1>
- Press Ctrl+O, then Enter to save.
- Press Ctrl+X to exit Nano.
- Run the curl command again to see your updated page:
curl http://localhost:8080
You should now see <h1>Hello from a Bind Mount!</h1> in the output. Your changes appeared without restarting the container.
Why is this useful for development?
Without a bind mount, you would need to rebuild the container image or copy files into the container every time you make a change. Bind mounts skip all of that by letting the container read files directly from your host in real time. This is the standard workflow for local development with Docker.
Changes not showing up?
- Make sure you saved the file in Nano before exiting. Run cat ~/docker-lab/html/index.html to confirm the new heading is in the file.
- Check that the container is still running with docker ps. If it is not listed, start it again with docker start my-nginx. Help me troubleshoot my live editing setup.
Pro tip: your docker-lab directory lives on
The ~/docker-lab directory you created in this step will be reused throughout the Docker Mastery series. In Part 2, you will write Dockerfiles here. In Part 3, you will add Compose files. Keep this directory around.
You now have a fully working Nginx container that serves your own custom HTML directly from your host machine. Every tool you have learned in this project forms the foundation for building, deploying, and debugging containers in the real world.
Secret mission
Docker Networking - Connect Containers by Name
You've mastered running individual containers. But in the real world, containers rarely work alone. A web server talks to a database. An API gateway routes to backend services. Can you create a custom Docker network where two containers discover each other by name?
Before you go
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally using Docker Engine, so there are no ongoing cloud costs.
Resources you used:
- Docker container: my-nginx (Nginx web server with bind mount).
- Docker image: nginx:1.27-alpine.
- Docker image: hello-world.
- Project directory: ~/docker-lab/html (custom HTML files).
- Custom bridge network and additional containers (if you completed the Secret Mission).
Keep everything running
No action needed. Choose this if you are still actively building or plan to continue with Part 2 of the Docker Mastery series right away.
- Your my-nginx container will keep running and serving your custom HTML page on port 8080.
- The ~/docker-lab directory will be reused in Parts 2 through 5 of this series.
Pause - I'll come back to this later
Shut down running containers to free up memory while keeping everything ready to restart later.
- Stop the Nginx container by running:
docker stop my-nginx
- Keep the ~/docker-lab directory and Docker images in place. They take up minimal disk space.
- When you are ready to resume, run docker start my-nginx to bring the container back up.
Delete - I don't want to use this again
Remove all project resources and start fresh. Only choose this if you do not plan to continue with the Docker Mastery series.
- Remove all containers created during this project:
docker rm -f my-nginx
- Remove the Docker images you pulled:
docker rmi nginx:1.27-alpine hello-world
- If you completed the Secret Mission, remove the custom network and any extra containers:
docker network rm my-network
- Delete the project directory:
rm -rf ~/docker-lab
- Run docker ps -a and docker images to confirm everything has been removed.
Mission accomplished
That's a Wrap!
Nice work! You just built the Docker CLI foundation that every DevOps and SRE engineer needs. You went from verifying your Docker Engine setup to serving custom content through a fully managed Nginx container.
Here's what you learned:
- Ran an Nginx web server in a container with port mapping and managed its full lifecycle with commands like docker stop, docker start, and docker rm.
- Debugged running containers using docker logs, docker exec, docker inspect, and docker stats to see exactly what is happening inside your containers.
- Served a custom HTML page from your host machine into a container using a bind mount with live-reloading changes and read-only security.
- Connected two containers on a custom bridge network with DNS-based service discovery, the same networking model that Docker Compose uses under the hood.
Ready to quiz yourself?