Docker containers are an excellent way to package and ship web servers in a repeatable, auditable fashion. This guide walks through writing a Dockerfile, building a custom Nginx image from it, and running that image as a container with port mapping exposed to the host. The original tutorial was authored by Neoxian on steemit.com, using James Turnbull’s The Docker Book as a reference.
What Is a Dockerfile?
A Dockerfile is a plain-text file containing a sequential list of instructions that Docker reads to automatically build an image. Instead of handing someone a pre-built image — which requires them to trust that nothing malicious was baked in — you can share a Dockerfile. Anyone can inspect every step, verify what is installed, and reproduce the exact same image themselves.
This transparency is one of the key reasons Dockerfiles are the standard way to distribute Docker-based applications in a DevOps workflow.
Example Dockerfile for an Nginx Web Server
Create a file named Dockerfile (no extension) with the following content:
# Version: 0.0.1
FROM ubuntu:16.04
MAINTAINER YourName
RUN apt-get update && apt-get install -y nginx
RUN echo 'Hello from the Docker container!' \
>/var/www/html/index.html
EXPOSE 80Code language: PHP (php)
Instruction Reference
#(comment) — Any line beginning with#is ignored by Docker. Use comments to document the purpose or version of the image.FROM— Sets the base image. Here,ubuntu:16.04is used as the starting point. Every Dockerfile must begin with aFROMinstruction.MAINTAINER— Records the author of the Dockerfile. This instruction is deprecated in newer Docker versions in favor of aLABELinstruction, but is still widely recognised.RUN— Executes a shell command inside the image during the build process. The firstRUNupdates the package index and installs Nginx. The second creates a minimalindex.htmlpage.EXPOSE— Documents that the container listens on port 80 at runtime. Note thatEXPOSEalone does not publish the port to the host; that requires the-pflag when running the container.
Building the Image
Create a dedicated directory for the project and place your Dockerfile inside it:
mkdir web
cd web
# Place your Dockerfile hereCode language: PHP (php)
From inside that directory, run the build command. Replace yourname with your Docker Hub username or any label you choose:
docker build -t="yourname/webserver" .Code language: JavaScript (javascript)
The trailing . tells Docker to look for the Dockerfile in the current directory. Docker will pull the base Ubuntu image (if not already cached), run each instruction in sequence, and produce a named image. Depending on your network speed and whether the base image is cached, this may take a few minutes.
Once the build completes, verify the image exists:
docker images
You should see yourname/webserver listed with its image ID, size, and creation time.
Running the Container
Start a container from your new image using the following command:
docker run --name webserver -p 5555:80 yourname/webserver nginx -g "daemon off;"Code language: JavaScript (javascript)
Breaking down the flags and arguments:
--name webserver— Assigns a human-readable name to the running container, making it easier to manage withdocker stop,docker rm, etc.-p 5555:80— Maps port 80 inside the container to port 5555 on the host. The format ishost_port:container_port. If you omit the host port (e.g.,-p 80), Docker assigns a random available port on the host. Use-p 80:80if you want the service to be reachable on the standard HTTP port.nginx -g "daemon off;"— Starts Nginx in the foreground. Docker containers exit as soon as their main process exits; running Nginx as a daemon (background process) would cause the container to stop immediately. Thedaemon offdirective keeps Nginx — and therefore the container — running.
Testing the Web Server
With the container running, open a browser and navigate to:
http://localhost:5555Code language: JavaScript (javascript)
You should see the message Hello from the Docker container! served by Nginx running inside the container. You can also test from the terminal:
curl http://localhost:5555Code language: JavaScript (javascript)
Stopping and Cleaning Up
When you are finished, stop and remove the container:
docker stop webserver
docker rm webserver
To remove the image as well:
docker rmi yourname/webserver
Next Steps
This example is intentionally minimal. In a real-world scenario you would likely:
- Use an official
nginxbase image instead of installing Nginx on top of Ubuntu, which produces a smaller and more maintainable image. - Use a
COPYinstruction to add your actual web content into the image at build time. - Replace
MAINTAINERwithLABEL maintainer="you@example.com", which is the current Docker best practice. - Use Docker Compose to orchestrate multi-container applications (e.g., web server + database).
- Pin the base image to a specific digest or at least a patch version for reproducible builds.
Reference: The Docker Book by James Turnbull was used as a reference for the original tutorial on which this article is based.