![](https://miro.medium.com/v2/resize:fit:1000/1*X-z4TTYKNalTjWDQeQC-FQ.png)
How Did I Set Up Docker for PHP in Just 30 Minutes?
Setting up Docker for PHP can sound big and scary, but it’s really not! 😄
Let’s dive in and see how I did it in just 30 minutes, which might help you too!
Install Docker
First, you need Docker on your computer. It’s like getting a new toy you need to put batteries in before you can play.
You can download it from the Docker website. Follow the instructions for your operating system, and voila, you’re set!
Create Your Dockerfile
A Dockerfile is like a recipe for Docker. It tells Docker what to do to set up your environment. Here’s a simple Dockerfile to get your PHP environment ready:
# Use the official PHP image from the Docker Hub
FROM php:8.3-apache
# Install all the PHP extensions you need
RUN docker-php-ext-install pdo_mysql
This Dockerfile starts with a PHP 8.3 image and adds the pdo_mysql
extension, which many PHP applications need to talk to a database.
PHP Setup
# Start from the official PHP image with Apache
FROM php:8.3-apache
# Install system dependencies and PHP extensions in one step
RUN apt-get update && apt-get install -y \
libpng-dev \
libonig-dev \
libxml2-dev \
libzip-dev \
zip \
curl \
unzip \
git \
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip \
&& a2enmod rewrite \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
This Dockerfile does everything in one RUN command:
- Updates package lists.
- Installs system dependencies needed by PHP extensions.
- Installs PHP extensions commonly used in web applications.
- Enables the Apache rewrite module for URL rewriting.
- Cleans up by removing unnecessary files to reduce the image size.
Build and run your Docker image with:
docker build -t my-php-app .
docker run -p 8080:80 my-php-app
This setup streamlines the installation into a single step, making your Dockerfile efficient and easy to manage.
Manage Your Services with Docker Compose
Now, we want to make managing our Docker container easier. That’s where Docker Compose comes in. It lets you manage multiple containers (like your web server, database, etc.) with just one file. Let’s create a docker-compose.yml
file:
version: '3.8'
services:
web:
build: .
ports:
- "8000:80"
volumes:
- .:/var/www/html
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: symfony
ports:
- "3306:3306"
This file sets up two services: web
(your PHP environment) and db
(a MySQL database). It builds the web service from the Dockerfile we created and keeps your code in sync with the container.
Run Everything with Docker Compose
Now, let’s start all our services with one command:
docker-compose up
When you run this, Docker Compose will set up both your PHP environment and your MySQL database, linked together. You can visit localhost:8000
to see your Symfony application in action, now with database superpowers! 💥
Add PHPMyAdmin for Database Management
Managing a database using the command line is cool, but sometimes, a graphical interface is handier, especially if you’re just starting out. Let’s add PHPMyAdmin to our Docker Compose setup:
version: '3.8'
services:
web:
build: .
ports:
- "8000:80"
volumes:
- .:/var/www/html
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: symfony
ports:
- "3306:3306"
phpmyadmin:
image: phpmyadmin/phpmyadmin
environment:
PMA_HOST: db
MYSQL_ROOT_PASSWORD: root
ports:
- "8080:80"
Now, run docker-compose up
again, and you can access PHPMyAdmin at localhost:8080
. This tool will make it much easier to view and manage your MySQL database through a friendly web interface.
Using Xdebug with PHP for Debugging
Debugging is like being a detective in your own code. Let’s add Xdebug to our Dockerfile to help us find bugs more efficiently. Here’s how you set it up:
# Install Xdebug
RUN pecl install xdebug \
&& docker-php-ext-enable xdebug
# Configure Xdebug
COPY xdebug.ini $PHP_INI_DIR/conf.d/
You’ll need to create an xdebug.ini
file with the proper configuration:
zend_extension=xdebug.so
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
This setup starts Xdebug with every request and communicates with your IDE at port 9003.
Log PHP Errors for Better Insight
It’s important to know what goes wrong when it goes wrong. Let’s configure PHP to log errors. Modify your Dockerfile to include these lines:
# Set PHP ini settings for error logging
RUN echo "log_errors = On" >> $PHP_INI_DIR/php.ini \
&& echo "error_log = /var/log/php_errors.log" >> $PHP_INI_DIR/php.ini
This will log PHP errors to /var/log/php_errors.log
inside your Docker container. You can check this log anytime to see what's happening if things aren't working right.
Set Up Automated Testing with PHPUnit
Automated testing is like having a robot that checks your homework. It’s a great way to catch mistakes early. Let’s add PHPUnit, a popular testing framework for PHP, to our Docker setup:
First, modify your Dockerfile to install PHPUnit:
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Install PHPUnit
RUN composer require --dev phpunit/phpunit ^9.5
This snippet installs Composer and then uses it to install PHPUnit. Composer is a tool for managing PHP package dependencies.
Next, create a simple PHPUnit test case. Here’s an example test for a hypothetical Calculator
class:
// tests/CalculatorTest.php
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
public function testAdd()
{
$calculator = new Calculator();
$this->assertEquals(4, $calculator->add(2, 2));
}
}
To run your tests, you can use the following command:
docker-compose run web vendor/bin/phpunit tests
This command tells Docker to run PHPUnit tests inside your web
service.
Introduce Continuous Integration with GitHub Actions
Continuous Integration (CI) means automatically testing your code every time you make changes. Let’s set up CI using GitHub Actions, which integrates directly with your GitHub repository:
Create a .github/workflows/php.yml
file in your repository with the following content:
name: PHP CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: pdo_mysql
- name: Validate composer.json and composer.lock
run: composer validate
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run Tests
run: vendor/bin/phpunit tests
This workflow configures GitHub Actions to set up a PHP environment, install dependencies, and run tests whenever you push changes to the main
branch or create a pull request.
Optimize Docker for Production
When moving from a development to a production environment, performance and security become top priorities. Let’s make a few changes to our Docker setup to enhance both.
Reduce Image Size
First, let’s optimize our Docker image to make it lighter and faster. This means using smaller base images and removing unnecessary files:
# Use a smaller base image
FROM php:8.3-fpm-alpine
# Install only the necessary extensions
RUN docker-php-ext-install pdo pdo_mysql
This uses the Alpine version of the PHP image, which is much smaller than the standard version.
Secure Your Application
Security in production is critical. Here are a few things you should do:
- Use environment variables for sensitive information (like database passwords).
- Ensure only necessary ports are exposed.
- Regularly update your images to include the latest security patches.
ENV MYSQL_PASSWORD="secure_password_here"
EXPOSE 80
Always store passwords and other sensitive data in environment variables and avoid hard-coding them into your application.
Set Up Continuous Deployment
Continuous Deployment (CD) means automatically deploying your application whenever you make changes. Let’s extend our GitHub Actions workflow to include deployment:
Add the following steps to your .github/workflows/php.yml
file:
- name: Build Docker Image
run: docker build -t my-php-app .
- name: Push Docker Image to Registry
run: |
echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
docker tag my-php-app ${{ secrets.DOCKER_USERNAME }}/my-php-app:latest
docker push ${{ secrets.DOCKER_USERNAME }}/my-php-app:latest
- name: Deploy to Production
run: echo "Deploying to production server..."
# Add your deployment script here
And we’re done! 🎉
We now have a full application set up with everything we need for it to work smoothly.
We’ve gone through installing Docker, setting up PHP with all the essential extensions, and integrating powerful tools and practices that elevate our development process.
This setup not only makes our application robust but also streamlines our workflow, ensuring we’re ready to tackle any project efficiently.
🔔 Click Subscribe to catch more coding fun.
👏🏻 Love it? Give a big clap.
💬 Got a cool idea or funny coding joke? Drop it in the comments.
Share these tips with your fellow developers to help each other succeed together.
Thanks for hanging out and reading. You rock! 🚀
Hold on a sec!!! Want more of my fun stuff in your inbox? Sign up here! 📩