The Nautilus Application development team recently finished development of one of the apps that they want to deploy on a containerized platform. The Nautilus Application development and DevOps teams met to discuss some of the basic pre-requisites and requirements to complete the deployment. The team wants to test the deployment on one of the app servers before going live and set up a complete containerized stack using a docker compose fie. Below are the details of the task:
- On
App Server 2inStratos Datacentercreate a docker compose file/opt/data/docker-compose.yml(should be named exactly). - The compose should deploy two services (web and DB), and each service should deploy a container as per details below:
For web service:
a. Container name must be php_host.
b. Use image php with any apache tag. Check here for more details.
c. Map php_host container's port 80 with host port 6200
d. Map php_host container's /var/www/html volume with host volume /var/www/html.
For DB service:
a. Container name must be mysql_host.
b. Use image mariadb with any tag (preferably latest). Check here for more details.
c. Map mysql_host container's port 3306 with host port 3306
d. Map mysql_host container's /var/lib/mysql volume with host volume /var/lib/mysql.
e. Set MYSQL_DATABASE=database_host and use any custom user ( except root ) with some complex password for DB connections.
- After running docker-compose up you can access the app with curl command
curl <server-ip or hostname>:6200/
For more details check here.
Note: Once you click on FINISH button, all currently running/stopped containers will be destroyed and stack will be deployed again using your compose file.
Introduction
Welcome to Day 46 of my 100 Days of DevOps journey! Today, we're going to learn how to deploy a complete application using Docker Compose. Don't worry if you're new to this – I'll explain everything step by step in simple terms.
What is Docker Compose?
Think of Docker Compose like a recipe book for your applications. Instead of manually running multiple docker run commands, you write all the instructions in a single file, and Docker Compose does everything for you with one command.
Why Use Docker Compose?
- One command to start everything
- Easy to manage multiple containers
- Consistent environment every time
- Simple to share with your team
📋 Our Task Today
We need to deploy a web application with a database on App Server 2. The application has two parts:
- Web Server (PHP) – serves the website
- Database (MariaDB) – stores data
🔧 Step-by-Step Guide
Step 1: Connect to the Server
First, let's connect to our server:
ssh steve@stapp02
# Enter password: Am3ric@
Once connected, switch to root user (administrator):
sudo su -
# Enter password: Am3ric@
Step 2: Create the Working Directory
Let's create a folder for our Docker Compose file:
mkdir -p /opt/data
cd /opt/data
Step 3: Install Docker Compose
Docker Compose might not be installed by default. Let's install it:
# Download Docker Compose
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# Make it executable
chmod +x /usr/local/bin/docker-compose
# Fix missing library (if needed)
yum install -y libxcrypt-compat
# Verify installation
docker-compose --version
What's happening here?
-
curldownloads the Docker Compose binary -
chmodmakes it executable -
yum installfixes any missing dependencies - The last command confirms it's working
Step 4: Create the Docker Compose File
Now, let's create our recipe file. Think of this as telling Docker what we want:
vi docker-compose.yml
Add this content:
version: '3.8'
services:
web:
image: php:apache
container_name: php_host
ports:
- "6200:80"
volumes:
- "/var/www/html:/var/www/html"
db:
image: mariadb:latest
container_name: mysql_host
ports:
- "3306:3306"
volumes:
- "/var/lib/mysql:/var/lib/mysql"
environment:
MYSQL_DATABASE: database_host
MYSQL_USER: dbuser
MYSQL_PASSWORD: 'ComplexPassword123!'
MYSQL_ROOT_PASSWORD: 'RootPassword123!'
📖 Understanding the YAML File
Let me explain what each part means:
Web Service (the website)
web:
image: php:apache # Use PHP with Apache
container_name: php_host # Name our container
ports:
- "6200:80" # Host port 6200 → Container port 80
volumes:
- "/var/www/html:/var/www/html" # Share files between host and container
DB Service (the database)
db:
image: mariadb:latest # Use MariaDB database
container_name: mysql_host # Name our container
ports:
- "3306:3306" # Host port 3306 → Container port 3306
volumes:
- "/var/lib/mysql:/var/lib/mysql" # Store database data
environment: # Set up database
MYSQL_DATABASE: database_host
MYSQL_USER: dbuser
MYSQL_PASSWORD: 'ComplexPassword123!'
MYSQL_ROOT_PASSWORD: 'RootPassword123!'
Step 5: Start the Application
Now the magic happens! Run this command to start everything:
docker-compose up -d
What this does:
-
docker-compose– runs Docker Compose -
up– starts the containers -
-d– runs in background (detached mode)
Step 6: Verify Everything is Working
Check if our containers are running:
# List running containers
docker-compose ps
Expected output:
Name Command State Ports
----------------------------------------------------------------------------------------------
mysql_host docker-entrypoint.sh mariadbd Up 0.0.0.0:3306->3306/tcp,:::3306->3306/tcp
php_host docker-php-entrypoint apac ... Up 0.0.0.0:6200->80/tcp,:::6200->80/tcp
Step 7: Test the Application
Finally, let's test if our application is working:
curl http://localhost:6200
If everything is working, you should see the default Apache welcome page or your website content.
🎯 Understanding What We Just Built
Container Architecture
┌─────────────────────────────────────────────┐
│ App Server 2 │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ php_host │ │ mysql_host │ │
│ │ │ │ │ │
│ │ Port: 6200 │ │ Port: 3306 │ │
│ │ Website: │ │ Database: │ │
│ │ /var/www/html │ │ /var/lib/mysql │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Host Volumes (persistent storage) │ │
│ │ - /var/www/html (web files) │ │
│ │ - /var/lib/mysql (database) │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
Key Concepts Explained
1. Images vs Containers
- Image: The blueprint/template (like a recipe)
- Container: Running instance of an image (like the cooked meal)
2. Port Mapping
-
"6200:80"means: When you access port 6200 on your server, it goes to port 80 in the container - This is how we access services from outside the container
3. Volumes
- Think of volumes as external hard drives
- They keep your data even if containers are deleted
- Both containers can access the same files
4. Environment Variables
- Settings that configure the database
- Like setting up a new user and database automatically
🔧 Troubleshooting Common Issues
Issue 1: Docker Compose Not Found
Error: docker-compose: command not found
Solution: Install Docker Compose (Step 3 above)
Issue 2: libcrypt.so.1 Error
Error: libcrypt.so.1: cannot open shared object file
Solution: yum install -y libxcrypt-compat
Issue 3: Permission Denied
Error: Permission denied while trying to connect to the Docker daemon
Solution: Add user to docker group:
usermod -aG docker steve
newgrp docker
Issue 4: Port Already in Use
Error: port is already allocated
Solution: Change the host port in the YAML file or stop the other service
📊 Quick Reference: Docker Compose Commands
| Command | Description |
|---|---|
docker-compose up -d |
Start containers in background |
docker-compose down |
Stop and remove containers |
docker-compose ps |
List running containers |
docker-compose logs |
View container logs |
docker-compose logs web |
View logs for web service |
docker-compose restart |
Restart containers |
docker-compose exec web bash |
Get shell inside web container |
✅ Summary
Today we learned:
- What is Docker Compose – A tool to manage multiple containers
- How to write a docker-compose.yml – Define services, ports, volumes
- How to deploy – One command to start everything
- How to verify – Check containers and test the application
Quick Command Summary
# Create directory
mkdir -p /opt/data && cd /opt/data
# Create compose file
vi docker-compose.yml
# Start everything
docker-compose up -d
# Check status
docker-compose ps
# Test
curl http://localhost:6200
Top comments (0)