SlideShare a Scribd company logo
1 of 34
Download to read offline
Hi there! I'm Erika
● DevOps Technical Writer
● Linux and open source enthusiast
● SysAdmin and PHP dev background
● Twitter: @erikaheidi
● Part 1: PHP development environments in the wild,
how Docker Compose fits in
● Part 2: Building a multi-container environment for
Laravel with Docker Compose
● Part 3: Demo
Talk Goals
Setting Expectations
Introduction:
Development Environments,
PHP, and Docker Compose
Part 1
PHP Development
Environments
A Delightful (and Personal) Timeline
● Part 1: PHP development environments in the wild,
how Docker Compose fits in
● Part 2: Building a multi-container environment for
Laravel with Docker Compose
● Part 3: Demo
Talk Goals
Setting Expectations
2000's
The Age of Wamp/Xampp and FTP
~2010
Local env and the rise of Git
● Pros:
○ Share, dispose and replicate full envs
○ Easy to Understand
● Cons:
○ Big Footprint
○ Depends on Automation Tools
~2012
Vagrant / VMs
● Pros:
○ Small footprint, fast and lightweight
○ Eliminates need for heavy automation
● Cons:
○ Not as intuitive as VMs
○ Defining and managing (micro) services
~2014
Docker / Containers
Docker Compose
A Hero to the Rescue
What is Compose
Docker Compose is a tool that allows you to run
multi-container application environments
based on definitions set in a YAML file.
It uses service definitions to build fully
customizable environments with multiple
containers that can share networks and data
volumes.
● Easy to set up and
manage
● Multiple composed
envs on a single host
● Preserves volume data
● Variables to allow
customization
Example
Nginx Service
docker-compose.yml
version: '3.7'
services:
web:
image: nginx
ports:
- "8000:80"
This simple
docker-compose.yml
file creates a service
container based on an
"nginx" image,
redirecting all requests
on local port 8000 to
port 80 in the container.
Up and
Running
docker-compose up
● Controlling the Environment
○ up | down | stop | start
● Monitoring & Troubleshooting
○ ps | logs | top | kill
● Executing Commands on containers
○ exec service_name command
Using Docker Compose
docker-compose [ command ]
Case Study
Travellist: a Laravel demo
application
Part 2
Travellist
A demo Laravel app
Environment Needs
Requirements for running PHP
Web Server: Nginx
We'll use Nginx to serve
the application in our
development
environment.
Database: MySQL
The application uses a
MySQL database to store
places and mark them as
"visited" or "to go".
PHP-FPM
PHP-FPM is required to
parse the PHP content
and return the results to
Nginx.
Application Needs
Laravel Requirements (DEV)
PHP Extensions
Laravel requires a few
different PHP extensions
that should be installed
on the application
container.
Artisan Commands
We need the ability to run
Artisan and Composer
commands from the host
machine.
Composer PHP
In order to install and
update Laravel's
dependencies, we'll need
Composer installed on the
application container.
Containers & Images
● Nginx
○ pre-built image
● MySQL
○ pre-built image
● App (PHP-FPM)
○ Image based on custom Dockerfile
Shared Volumes & Networks
Volumes
● Application files
○ host app, nginx
● Nginx configuration file
○ host nginx
● MySQL database dump
○ host mysql
Networks
● host app, nginx, mysql
Setting Up a
docker-compose.yml
Configuring service containers, volumes and
networks
App+PHPdocker-compose.yml
app:
build:
context: ./
dockerfile: Dockerfile
image: travellist
container_name: travellist-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- travellist
This service will be
responsible for parsing
all PHP requests and
command-line calls
made with Composer
and Artisan. It will build
a new image based on
the provided Dockerfile.
Nginxdocker-compose.yml
nginx:
image: nginx:1.17-alpine
container_name: travellist-nginx
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d
networks:
- travellist
This service will be
responsible for serving
the application via
Nginx. A port
redirection will allow us
to access port 80 inside
the container through
port 8000 in the host.
DBdocker-compose.yml
db:
image: mysql:5.7
container_name: travellist-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
...
This service will run a
MySQL database to
store the application's
data. It will extract
values from the .env
Laravel file to create a
new DB and user.
DB (cont)docker-compose.yml
...
volumes:
- ./docker-compose/mysql:/docker-entrypoint-initdb.d
networks:
- travellist
The shared volume
contains a .sql file that
will be automatically
imported (a feature
provided by this image).
App Dockerfile
Building a custom image based on php-fpm to
meet application needs
Dockerfile
App+PHP
container
Dockerfile
FROM php:7.4-fpm
ARG uid=1000
ARG user=sammy
RUN apt-get update && apt-get install -y 
git 
curl 
libpng-dev 
libonig-dev 
libxml2-dev 
zip 
unzip
...
This Dockerfile will build
a new image based on
the php:7.4-fpm
official PHP image.
We start by installing
some required system
packages.
Dockerfile
App+PHP
container
Dockerfile
…
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && 
chown -R $user:$user /home/$user
...
Variables are used to
create a new user and
grant them the same
privileges as your
current system user on
the host, so that you
don't run into
permission issues with
synced files.
Dockerfile
App+PHP
container
Dockerfile
...
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Set working directory
WORKDIR /var/www
USER $user
We then install
Composer, set the work
dir and change to the
new user, so that when
we run commands via
docker-compose exec,
they are executed as
the new system user.
Directory
Tree
TERMINAL
application/
├── docker-compose
│ ├── mysql
│ │ └── init_db.sql
│ └── nginx
| └── travellist.conf
├── Dockerfile
└── docker-compose.yml
Here's an overview of
what our Docker
Compose setup looks
like, excluding the
application files.
Demo Time!
Part 3
Questions?
@erikaheidi
THANK YOU!
@erikaheidi

More Related Content

More from DigitalOcean

Build, Deploy, and Scale Your First Web App Using DigitalOcean App Platform
Build, Deploy, and Scale Your First Web App Using DigitalOcean App PlatformBuild, Deploy, and Scale Your First Web App Using DigitalOcean App Platform
Build, Deploy, and Scale Your First Web App Using DigitalOcean App PlatformDigitalOcean
 
Effective Kubernetes Onboarding
Effective Kubernetes OnboardingEffective Kubernetes Onboarding
Effective Kubernetes OnboardingDigitalOcean
 
Creating Inclusive Learning Experiences
Creating Inclusive Learning ExperiencesCreating Inclusive Learning Experiences
Creating Inclusive Learning ExperiencesDigitalOcean
 
Kubernetes for Beginners
Kubernetes for BeginnersKubernetes for Beginners
Kubernetes for BeginnersDigitalOcean
 
Command-line Your Way to PaaS Productivity With DigitalOcean App Platform
Command-line Your Way to PaaS Productivity With DigitalOcean App PlatformCommand-line Your Way to PaaS Productivity With DigitalOcean App Platform
Command-line Your Way to PaaS Productivity With DigitalOcean App PlatformDigitalOcean
 
Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...
Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...
Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...DigitalOcean
 
Kubernetes: Beyond Baby Steps
Kubernetes: Beyond Baby StepsKubernetes: Beyond Baby Steps
Kubernetes: Beyond Baby StepsDigitalOcean
 
How to Leverage Go for Your Networking Needs
How to Leverage Go for Your Networking NeedsHow to Leverage Go for Your Networking Needs
How to Leverage Go for Your Networking NeedsDigitalOcean
 
Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...
Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...
Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...DigitalOcean
 
Secrets to Building & Scaling SRE Teams
Secrets to Building & Scaling SRE TeamsSecrets to Building & Scaling SRE Teams
Secrets to Building & Scaling SRE TeamsDigitalOcean
 
Deploying to DigitalOcean With GitHub Actions
Deploying to DigitalOcean With GitHub ActionsDeploying to DigitalOcean With GitHub Actions
Deploying to DigitalOcean With GitHub ActionsDigitalOcean
 
Building an Observability Platform in 389 Difficult Steps
Building an Observability Platform in 389 Difficult StepsBuilding an Observability Platform in 389 Difficult Steps
Building an Observability Platform in 389 Difficult StepsDigitalOcean
 
Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...
Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...
Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...DigitalOcean
 
Developer Burnout: Yes, You Can Improve Your Team's Wellness
Developer Burnout: Yes, You Can Improve Your Team's WellnessDeveloper Burnout: Yes, You Can Improve Your Team's Wellness
Developer Burnout: Yes, You Can Improve Your Team's WellnessDigitalOcean
 
Why Should You Care About Your Customer's Journey?
Why Should You Care About Your Customer's Journey?Why Should You Care About Your Customer's Journey?
Why Should You Care About Your Customer's Journey?DigitalOcean
 
Build Apps Faster With DigitalOcean App Platform
Build Apps Faster With DigitalOcean App PlatformBuild Apps Faster With DigitalOcean App Platform
Build Apps Faster With DigitalOcean App PlatformDigitalOcean
 

More from DigitalOcean (16)

Build, Deploy, and Scale Your First Web App Using DigitalOcean App Platform
Build, Deploy, and Scale Your First Web App Using DigitalOcean App PlatformBuild, Deploy, and Scale Your First Web App Using DigitalOcean App Platform
Build, Deploy, and Scale Your First Web App Using DigitalOcean App Platform
 
Effective Kubernetes Onboarding
Effective Kubernetes OnboardingEffective Kubernetes Onboarding
Effective Kubernetes Onboarding
 
Creating Inclusive Learning Experiences
Creating Inclusive Learning ExperiencesCreating Inclusive Learning Experiences
Creating Inclusive Learning Experiences
 
Kubernetes for Beginners
Kubernetes for BeginnersKubernetes for Beginners
Kubernetes for Beginners
 
Command-line Your Way to PaaS Productivity With DigitalOcean App Platform
Command-line Your Way to PaaS Productivity With DigitalOcean App PlatformCommand-line Your Way to PaaS Productivity With DigitalOcean App Platform
Command-line Your Way to PaaS Productivity With DigitalOcean App Platform
 
Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...
Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...
Escape the Walls of PaaS: Unlock the Power & Flexibility of DigitalOcean App ...
 
Kubernetes: Beyond Baby Steps
Kubernetes: Beyond Baby StepsKubernetes: Beyond Baby Steps
Kubernetes: Beyond Baby Steps
 
How to Leverage Go for Your Networking Needs
How to Leverage Go for Your Networking NeedsHow to Leverage Go for Your Networking Needs
How to Leverage Go for Your Networking Needs
 
Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...
Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...
Combining Cloud Native & PaaS: Building a Fully Managed Application Platform ...
 
Secrets to Building & Scaling SRE Teams
Secrets to Building & Scaling SRE TeamsSecrets to Building & Scaling SRE Teams
Secrets to Building & Scaling SRE Teams
 
Deploying to DigitalOcean With GitHub Actions
Deploying to DigitalOcean With GitHub ActionsDeploying to DigitalOcean With GitHub Actions
Deploying to DigitalOcean With GitHub Actions
 
Building an Observability Platform in 389 Difficult Steps
Building an Observability Platform in 389 Difficult StepsBuilding an Observability Platform in 389 Difficult Steps
Building an Observability Platform in 389 Difficult Steps
 
Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...
Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...
Doing This Cloud Thing Right – a Lap Around DigitalOcean Products and a Roadm...
 
Developer Burnout: Yes, You Can Improve Your Team's Wellness
Developer Burnout: Yes, You Can Improve Your Team's WellnessDeveloper Burnout: Yes, You Can Improve Your Team's Wellness
Developer Burnout: Yes, You Can Improve Your Team's Wellness
 
Why Should You Care About Your Customer's Journey?
Why Should You Care About Your Customer's Journey?Why Should You Care About Your Customer's Journey?
Why Should You Care About Your Customer's Journey?
 
Build Apps Faster With DigitalOcean App Platform
Build Apps Faster With DigitalOcean App PlatformBuild Apps Faster With DigitalOcean App Platform
Build Apps Faster With DigitalOcean App Platform
 

Recently uploaded

What is a Recruitment Management Software?
What is a Recruitment Management Software?What is a Recruitment Management Software?
What is a Recruitment Management Software?NYGGS Automation Suite
 
Community is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea GouletCommunity is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea GouletAndrea Goulet
 
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...naitiksharma1124
 
^Clinic ^%[+27788225528*Abortion Pills For Sale In witbank
^Clinic ^%[+27788225528*Abortion Pills For Sale In witbank^Clinic ^%[+27788225528*Abortion Pills For Sale In witbank
^Clinic ^%[+27788225528*Abortion Pills For Sale In witbankkasambamuno
 
GraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with Graph
GraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with GraphGraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with Graph
GraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with GraphNeo4j
 
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024SimonedeGijt
 
Weeding your micro service landscape.pdf
Weeding your micro service landscape.pdfWeeding your micro service landscape.pdf
Weeding your micro service landscape.pdftimtebeek1
 
Prompt Engineering - an Art, a Science, or your next Job Title?
Prompt Engineering - an Art, a Science, or your next Job Title?Prompt Engineering - an Art, a Science, or your next Job Title?
Prompt Engineering - an Art, a Science, or your next Job Title?Maxim Salnikov
 
Auto Affiliate AI Earns First Commission in 3 Hours..pdf
Auto Affiliate  AI Earns First Commission in 3 Hours..pdfAuto Affiliate  AI Earns First Commission in 3 Hours..pdf
Auto Affiliate AI Earns First Commission in 3 Hours..pdfSelfMade bd
 
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...Neo4j
 
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit MilanWorkshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit MilanNeo4j
 
OpenChain Webinar: AboutCode and Beyond - End-to-End SCA
OpenChain Webinar: AboutCode and Beyond - End-to-End SCAOpenChain Webinar: AboutCode and Beyond - End-to-End SCA
OpenChain Webinar: AboutCode and Beyond - End-to-End SCAShane Coughlan
 
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...Flutter Agency
 
Evolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI EraEvolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI Eraconfluent
 
Software Engineering - Introduction + Process Models + Requirements Engineering
Software Engineering - Introduction + Process Models + Requirements EngineeringSoftware Engineering - Introduction + Process Models + Requirements Engineering
Software Engineering - Introduction + Process Models + Requirements EngineeringPrakhyath Rai
 
Modern binary build systems - PyCon 2024
Modern binary build systems - PyCon 2024Modern binary build systems - PyCon 2024
Modern binary build systems - PyCon 2024Henry Schreiner
 
Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...
Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...
Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...Abortion Clinic
 

Recently uploaded (20)

What is a Recruitment Management Software?
What is a Recruitment Management Software?What is a Recruitment Management Software?
What is a Recruitment Management Software?
 
Community is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea GouletCommunity is Just as Important as Code by Andrea Goulet
Community is Just as Important as Code by Andrea Goulet
 
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
COMPUTER AND ITS COMPONENTS PPT.by naitik sharma Class 9th A mittal internati...
 
^Clinic ^%[+27788225528*Abortion Pills For Sale In witbank
^Clinic ^%[+27788225528*Abortion Pills For Sale In witbank^Clinic ^%[+27788225528*Abortion Pills For Sale In witbank
^Clinic ^%[+27788225528*Abortion Pills For Sale In witbank
 
GraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with Graph
GraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with GraphGraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with Graph
GraphSummit Milan & Stockholm - Neo4j: The Art of the Possible with Graph
 
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
Wired_2.0_CREATE YOUR ULTIMATE LEARNING ENVIRONMENT_JCON_16052024
 
Weeding your micro service landscape.pdf
Weeding your micro service landscape.pdfWeeding your micro service landscape.pdf
Weeding your micro service landscape.pdf
 
Prompt Engineering - an Art, a Science, or your next Job Title?
Prompt Engineering - an Art, a Science, or your next Job Title?Prompt Engineering - an Art, a Science, or your next Job Title?
Prompt Engineering - an Art, a Science, or your next Job Title?
 
Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...
Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...
Abortion Clinic Pretoria ](+27832195400*)[ Abortion Clinic Near Me ● Abortion...
 
Auto Affiliate AI Earns First Commission in 3 Hours..pdf
Auto Affiliate  AI Earns First Commission in 3 Hours..pdfAuto Affiliate  AI Earns First Commission in 3 Hours..pdf
Auto Affiliate AI Earns First Commission in 3 Hours..pdf
 
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
 
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit MilanWorkshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
 
OpenChain Webinar: AboutCode and Beyond - End-to-End SCA
OpenChain Webinar: AboutCode and Beyond - End-to-End SCAOpenChain Webinar: AboutCode and Beyond - End-to-End SCA
OpenChain Webinar: AboutCode and Beyond - End-to-End SCA
 
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
Navigation in flutter – how to add stack, tab, and drawer navigators to your ...
 
Evolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI EraEvolving Data Governance for the Real-time Streaming and AI Era
Evolving Data Governance for the Real-time Streaming and AI Era
 
Software Engineering - Introduction + Process Models + Requirements Engineering
Software Engineering - Introduction + Process Models + Requirements EngineeringSoftware Engineering - Introduction + Process Models + Requirements Engineering
Software Engineering - Introduction + Process Models + Requirements Engineering
 
Modern binary build systems - PyCon 2024
Modern binary build systems - PyCon 2024Modern binary build systems - PyCon 2024
Modern binary build systems - PyCon 2024
 
Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...
Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...
Abortion Pill Prices Jane Furse ](+27832195400*)[ 🏥 Women's Abortion Clinic i...
 
Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...
Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...
Abortion Clinic In Pretoria ](+27832195400*)[ 🏥 Safe Abortion Pills in Pretor...
 
Abortion Clinic In Johannesburg ](+27832195400*)[ 🏥 Safe Abortion Pills in Jo...
Abortion Clinic In Johannesburg ](+27832195400*)[ 🏥 Safe Abortion Pills in Jo...Abortion Clinic In Johannesburg ](+27832195400*)[ 🏥 Safe Abortion Pills in Jo...
Abortion Clinic In Johannesburg ](+27832195400*)[ 🏥 Safe Abortion Pills in Jo...
 

How to Create PHP Developer Environments With Docker Compose