Docker has revolutionized software deployment by packaging applications with all their dependencies. In this guide, we won't just look at commands; we will explore the practical use cases for different types of containers, from ephemeral testing environments to persistent database storage.
1. Running Web Servers as Containers
One of the most common use cases for Docker is deploying web servers. Unlike installing Apache or Nginx directly on your OS, running them in a container ensures that your host system remains clean.
Use the httpd image (Apache HTTP Server) to quickly launch a web server instance.
docker run --name webserver -d -p 8080:80 httpd
Understanding the Flags:
-d(Detached): Runs the container in the background so it doesn't block your terminal.-p 8080:80(Port Mapping): Maps port 8080 on your laptop (Host) to port 80 inside the container. You access it vialocalhost:8080.
Check the status of your running containers:
docker container ls
Alternatively, use the -P flag to map the container's exposed port to a random high port on the host. This is useful for scaling when you don't care which specific port is used:
docker run --name appserver -d -P httpd
Pro Tip: Port Conflicts
If you try to run two containers on port 8080, the second will fail with a "Bind Address" error. Always ensure your Host Port (the first number in 8080:80) is unique for each running container.
2. Operating Systems as Containers
Why run an OS inside an OS? Docker allows running lightweight OS environments (like Ubuntu or Alpine) for testing scripts, compiling code, or administrative tasks without the overhead of a Virtual Machine.
Run and access an Ubuntu terminal. The -it flags are crucial here—they attach your terminal input to the container's output.
docker run --name myubuntu -it ubuntu
This opens an Ubuntu terminal where you can execute commands:
root@0ffb094e529e:/#
Exit the session with: exit. Note that once you exit, the container stops running because its main process (bash) has finished.
Run CentOS similarly:
docker run --name mycentos -it centos
Clean up both OS containers:
docker rm -f mycentos myubuntu
3. SQL Databases as Containers
Running stateful applications like MySQL requires careful handling. A common mistake beginners make is failing to provide mandatory configuration environment variables.
Incorrect Example
docker run --name mydb -d mysql
Why it fails: The MySQL image checks for a root password on startup. If it's missing, the container crashes immediately.
Correct Example
You must provide the root password using the -e (Environment) flag:
docker run --name mydb -d -e MYSQL_ROOT_PASSWORD=secret123 mysql
Access the database shell once the container is running:
docker exec -it mydb bash
Inside the container, log into the MySQL server:
bash-4.4# mysql -u root -p
After successful login, you can create databases and tables. Exit the MySQL client with: mysql exit;
Warning: Data Persistence
In the example above, if you delete the container (docker rm mydb), all your data is lost. For production, you must use Docker Volumes to map the database storage path (/var/lib/mysql) to your host system.
4. Container Communication (Multi-Container Architecture)
Modern applications are rarely single monoliths. They are composed of multiple services (e.g., a web front-end talking to a database backend). To achieve this, containers must communicate securely.
Evolution of Networking:
--link: Deprecated. Only used for legacy systems. It injected environment variables into containers.- Docker Networks: The modern standard. Containers joined to the same user-defined network can resolve each other by container name (DNS).
Example: Legacy Linking (Conceptual)
Although deprecated, you may see this in old tutorials. It links two containers directly.
1. Start the source container:
docker run --name containerA -it busybox
*(Use Ctrl+P, Ctrl+Q to detach without stopping)*
2. Start the second container and link it:
docker run --name containerB -it --link containerA:myalias busybox
Inside containerB, you could then ping containerA or its alias.
The Modern Approach:
# Create a network
docker network create mynet
# Run containers on that network
docker run -d --name db --network mynet mysql
docker run -d --name web --network mynet wordpress
In this modern approach, the web container simply connects to the hostname db.
📝 Key Takeaways
1. Containers are ephemeral; always use volumes for Databases.
2. Use -d for servers and -it for interactive OS shells.
3. Stop using --link; learn Docker Compose for defining multi-container applications.