Local E-commerce Made Easy: Harnessing Docker and Docker Compose


In a previous article, we discussed deploying our e-commerce application on a single Google Compute Engine VM. Now, let's go back to the early 2000s when the flexibility of Docker was the new frontier! Before considering Kubernetes for production, we'll focus on getting our e-commerce example running locally using Docker for efficient testing and development.
To simplify the setup, we'll use Cloud Shell to run our Docker environment. Cloud Shell has Docker and Docker Compose already installed, so you don't need to handle any local installations or configurations. This allows us to quickly get your e-commerce application running and tested without any hassle.
For our e-commerce setup, we'll use the KodeKloudHub Learning App E-commerce repository, which provides a PHP Apache-based application for this purpose.
Now, let's create a Dockerfile
for our e-commerce application. This file will specify how to build our Docker image, including the base image, required extensions, and the location of our application code.
FROM php:7.4-apache
# Install the mysqli extension, which is required for database interaction
RUN docker-php-ext-install mysqli
# Copy all files from the current directory (where the Dockerfile is located)
# into the /var/www/html/ directory of the Apache server inside the container.
# This makes our e-commerce application code available to the web server.
COPY . /var/www/html/
This Dockerfile
sets up a basic PHP 7.4 Apache environment, installs the mysqli
extension needed for database connectivity, and copies our application code into the web server's document root. Next, we'll see how to build a container.
Building and Running the Docker Container
With our Dockerfile
ready, we can build the Docker image and run a container from it. This will package our application and its dependencies into a portable unit.
First, we will go to the directory where we saved our Dockerfile
and the e-commerce application code (after cloning the KodeKloudHub repository). Then, use the docker build
command to create our image:
$ docker build -t ecommerce-app .
docker build
: This command starts the process of building the image.-t ecommerce-app
: This tags the image with the nameecommerce-app
. You can choose any name you prefer..
: This indicates the build context, meaning Docker will search for theDockerfile
in the current directory.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ecomapp latest 4f4440e2d28f 7 seconds ago 459MB
Once the image is built, we will run a container from it using the docker run
command:
$ docker run -d -p 8080:80 --name ecommerce-container ecommerce-app
docker run
: This command creates and starts a new container from an image.-p 8080:80
: This is important for accessing our application. It maps port8080
on our host machine (Cloud Shell in this case) to port80
inside the container (where Apache is listening).-d
: Run in detached mode.--name ecommerce-container
: This gives a recognizable name to our running container, making it easier to manage later.ecommerce-app
: This is the name of the image we just built.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3ea54a5de75f ecomapp "docker-php-entrypoi…" 56 seconds ago Up 56 seconds 0.0.0.0:8080->80/tcp ecomcontainer
After running this command, our e-commerce application should be accessible through the Cloud Shell's "Web Preview" feature on port 8080. However, we will see a connection error right away. This happens because our e-commerce application needs a database, and right now, we've only started the PHP Apache server. We need a way to run multiple containers together and manage their networking. This is where Docker Compose is useful.
Using Docker Compose for Multi-Container Applications
Docker Compose is a tool that helps you define and run applications with multiple Docker containers. With Compose, you use a YAML file to set up your application's services, networks, and storage. This lets you start your whole application stack with just one command.
Let's create a docker-compose.yml
file in the root of our e-commerce project. This file will define two services: our app
(the PHP Apache application) and a db
service (a MariaDB database).
version: '3.3'
services:
app:
# Build the Docker image from the Dockerfile in the current directory.
build: .
ports:
# Map port 8080 on your host machine to port 80 in the container.
- "8080:80"
environment:
# Pass database connection details to the application as environment variables.
DB_HOST: db
DB_USER: ecomuser
DB_PASSWORD: ecompassword
DB_NAME: ecomdb
# Ensure the 'db' service is started before the 'app' service.
depends_on:
- db
# The 'db' service for your MariaDB database.
db:
image: mariadb:10.6
restart: always
environment:
MYSQL_ROOT_PASSWORD: verysecretrootpassword
MYSQL_DATABASE: ecomdb
MYSQL_USER: ecomuser
MYSQL_PASSWORD: ecompassword
volumes:
# Mount the SQL script to initialize the database on first startup.
- ./assets/db-load-script.sql:/docker-entrypoint-initdb.d/init.sql
# Use a volume to persist database data.
- db_data:/var/lib/mysql
# volume for database persistence.
volumes:
db_data:
version: '3.3'
: This line sets the Docker Compose file format version.
services:
: This is the main section where we define all the individual containers (services) that make up our application. Each service operates in its own isolated environment.
The app
Service (Your E-commerce Application)
app:
: This defines our e-commerce PHP application service.build: .
: This tells Docker Compose to build the Docker image for this service using theDockerfile
located in the current directory (.
). This is theDockerfile
we created earlier.ports:
: This maps network ports between the host machine (Cloud Shell in this case) and the container.- "8080:80"
: This means that traffic on port8080
of our host machine will be forwarded to port80
inside theapp
container. Since Apache usually listens on port 80, this allows our web application to be accessed from outside the container via the Cloud Shell Web Preview URL.
environment:
: This section allows us to define environment variables that will be available inside theapp
container. These are crucial for our PHP application to connect to the database.DB_HOST: db
: This is a key setting. Inside the Docker Compose network, services can communicate with each other using their service names as hostnames. So,db
refers to thedb
service defined later in this file.
DB_USER: ecomuser
,DB_PASSWORD: ecompassword
,DB_NAME: ecomdb
: These variables provide the credentials and database name needed for our PHP application to connect to the MariaDB database. They must match the settings configured for thedb
service.depends_on:
: This sets up a dependency between services.- db
: This tells Docker Compose that theapp
service depends on thedb
service. Whiledepends_on
ensuring thedb
container starts before theapp
container.
The db
Service (MariaDB Database)
db:
: This sets up our database service, which will run a MariaDB instance.
image: mariadb:10.6
: This tells Docker Compose to use themariadb
image with the10.6
tag from Docker Hub. This image includes the MariaDB database server.restart: always
: This policy ensures that if thedb
container stops for any reason (like an error or host reboot), Docker will automatically try to restart it.environment:
: Like theapp
service, these environment variables configure the MariaDB server when it starts for the first time.MYSQL_ROOT_PASSWORD
,MYSQL_DATABASE
,MYSQL_USER
,MYSQL_PASSWORD
: These variables set the root password, the default database nameecomdb
, and a specific userecomuser
with a passwordecompassword
for that database. These credentials are used by ourapp
service to connect.volumes:
: This section is essential for managing data in Docker. Volumes allow data generated by Docker containers to be saved.- ./assets/db-load-script.sql:/docker-entrypoint-initdb.d/init.sql
: This is a bind mount. It mounts a local file./assets/db-load-script.sql
from our project directory into a specific directory inside the MariaDB container. Thedocker-entrypoint-initdb.d/
directory is special for MariaDB/MySQL images; any.sql
scripts placed here will automatically run when the container starts for the first time, allowing you to pre-populate your database with schemas and initial data. Make sure thisdb-load-script.sql
file exists inassets
folder relative to ourdocker-compose.yml
.- db_data:/var/lib/mysql
: This uses a named volumedb_data
to save the actual database files/var/lib/mysql
is where MariaDB stores its data. This means that even if we stop, remove, and recreate thedb
container, our database data will not be lost because it's stored on the host machine in thedb_data
volume.Volumes Definition
volumes:
: This top-level key is where we define named volumes that can be shared and reused by services.db_data:
: This line defines a named volume calleddb_data
. Docker handles the creation and storage location of this volume on the host system. It's a best practice for saving data because it's more reliable than bind mounts for data that needs to exist beyond the container's lifecycle.
In summary, this docker-compose.yml
file sets up a complete self-contained e-commerce environment with a PHP Apache application and a MariaDB database. It ensures they can communicate, data is saved, and the setup is easy to reproduce.
$ docker compose up -d
Once you run docker compose up -d
our application goes live! We can then interact with our services on port 8080
as we defined. Look for the "Web Preview" button in the Cloud Shell toolbar. Clicking it will usually let you choose "Preview on port 8080" which will open a new browser tab or window showing your running application.
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------------
learning-app-ecommerce_app_1 docker-php-entrypoint apac ... Up 0.0.0.0:8080->80/tcp
learning-app-ecommerce_db_1 docker-entrypoint.sh mariadbd Up 3306/tcp
Conclusion: Tearing Down and Looking Ahead
We've successfully launched our multi-container application using docker compose up -d
, checked its running status with docker compose ps
, and learned how Docker Compose smoothly manages communication between services and data storage.
When we're ready to shut down our application and clean up all related resources, including the data stored in named volumes, we'll use the following command:
$ docker compose down -v
This complete method for defining, running, and shutting down multi-container applications with Docker Compose offers a powerful and flexible local development setup. We've learned the basics of managing our services effectively.
But what do you do when your application becomes too large for your local machine? How do you scale it, ensure it's always available, and manage it in a production setting?
In our next article, we'll make the exciting jump from local Docker Compose deployments to enterprise-level orchestration. Get ready as we explore how to host and manage your application on Kubernetes.
Subscribe to my newsletter
Read articles from bablu directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
