Symfony Functions

 

Symfony and Docker: Containerizing Your Applications

In today’s fast-paced development landscape, containerization has become a fundamental practice for building and deploying applications efficiently. Docker, an industry-standard containerization platform, allows developers to package their applications and dependencies into containers, ensuring seamless deployment across various environments. Symfony, a popular PHP framework, can also benefit from Docker’s containerization capabilities. In this blog, we will explore how to containerize Symfony applications with Docker, enabling scalability, portability, and consistency in the development process.

Symfony and Docker: Containerizing Your Applications

Symfony is a mature and robust PHP framework known for its flexibility, modularity, and ease of use. It powers a vast number of web applications, ranging from small projects to enterprise-level systems. On the other hand, Docker has revolutionized the way applications are developed and deployed. By encapsulating the application and its dependencies within a container, Docker ensures consistency between development, testing, and production environments.

In this blog, we will guide you through the process of containerizing a Symfony application with Docker. By doing so, you’ll gain several advantages, such as streamlined deployments, improved scalability, simplified dependency management, and a unified development experience across teams.

1. Understanding Docker and Containers

1.1 What is Docker?

Docker is an open-source platform that enables developers to automate the deployment of applications inside lightweight, portable containers. A container is a standalone executable package that includes everything needed to run the application, such as code, runtime, libraries, and dependencies. Docker allows you to create, manage, and distribute containers, ensuring that the application runs consistently across different environments.

1.2 Advantages of Using Containers

Containerization offers several benefits for Symfony applications:

  • Isolation: Containers isolate the application from the underlying system, eliminating potential conflicts with other applications or libraries.
  • Portability: Containers can run on any system that supports Docker, ensuring consistent behavior regardless of the hosting environment.
  • Scalability: Docker allows easy scaling of containers horizontally, enabling the application to handle varying loads effectively.
  • Consistency: With containers, the development and production environments become consistent, reducing the “it works on my machine” problem.
  • Dependency Management: Docker allows you to define and manage the application’s dependencies in a standardized way, making the deployment process more straightforward.

2. Preparing Symfony for Dockerization

Before we containerize our Symfony application, we need to set up a Symfony project and organize its dependencies and configuration.

2.1 Setting Up Symfony Project

First, make sure you have Symfony CLI installed on your system. If not, follow the official installation guide: Symfony CLI Installation.

To create a new Symfony project, run the following command:

bash
symfony new my_symfony_app --full

This will create a new Symfony project with all the standard components included.

2.2 Defining Dependencies and Configuration

Next, navigate to the newly created project directory:

bash
cd my_symfony_app

In a Symfony application, dependencies are managed using Composer, so we need to ensure that the composer.json file is present and includes all required dependencies. Once you’ve added or modified the dependencies, run:

bash
composer install

Now, configure your Symfony application as per your specific requirements, making any necessary adjustments to the database connection, caching, and other services.

3. Creating a Dockerfile for Symfony

A Dockerfile is a text document that contains all the commands required to assemble a Docker image. To containerize our Symfony application, we need to create a Dockerfile.

3.1 Base Image Selection

The first step is to select a base image for our Symfony application. We’ll use an official PHP base image, which is available on Docker Hub:

Dockerfile
FROM php:8.0-fpm

This base image includes PHP and FPM (FastCGI Process Manager) to serve PHP applications efficiently.

3.2 Copying Symfony Files

Next, we need to copy our Symfony application files into the Docker image. We’ll use the COPY command to achieve this:

Dockerfile
WORKDIR /var/www/html
COPY . /var/www/html

This sets the working directory inside the container to /var/www/html and copies all the files from our current directory (Symfony project directory) into the container’s working directory.

3.3 Installing Dependencies

To run a Symfony application, we need to install its dependencies. We can achieve this by executing Composer inside the container:

Dockerfile
RUN apt-get update \
    && apt-get install -y libzip-dev zip \
    && docker-php-ext-configure zip --with-libzip \
    && docker-php-ext-install zip pdo pdo_mysql
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer install

Here, we install the required system dependencies, enable the PHP zip extension, and install the PHP extensions needed to run Symfony. Additionally, we install Composer and execute composer install to install the application-specific dependencies.

3.4 Exposing the Application

Finally, we need to expose the PHP-FPM port, allowing us to access the Symfony application from the host:

Dockerfile
EXPOSE 9000

This command informs Docker that the container will listen on port 9000, which is the default port for PHP-FPM.

4. Building the Docker Image

With the Dockerfile ready, we can now build the Docker image for our Symfony application.

4.1 Building the Image

To build the Docker image, execute the following command in the same directory as your Dockerfile:

bash
docker build -t my_symfony_app .

Here, -t is used to tag the image with a name (my_symfony_app in this case).

4.2 Verifying the Image

Once the build process completes, you can verify that the image is created successfully by running:

bash
docker images

You should see the newly built image in the list.

5. Docker Compose for Symfony

In a real-world scenario, Symfony applications often require additional services, such as databases or caches. Instead of managing these services manually, Docker Compose allows us to define and manage multi-container applications easily.

5.1 What is Docker Compose?

Docker Compose is a tool for defining and running multi-container Docker applications using a YAML file. It enables you to specify all the services, networks, and volumes required for your application to run.

5.2 Compose File for Symfony

Create a docker-compose.yml file in your Symfony project’s root directory and define the services required for your Symfony application:

yaml
version: '3.8'

services:
  php:
    build: .
    container_name: my_symfony_app
    volumes:
      - .:/var/www/html
    ports:
      - "9000:9000"
    depends_on:
      - db

  db:
    image: mysql:5.7
    container_name: my_symfony_db
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: symfony_db
      MYSQL_USER: symfony_user
      MYSQL_PASSWORD: symfony_password
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

In this docker-compose.yml file, we define two services: php (our Symfony application) and db (MySQL database). We use the build directive to specify the context for the Docker build (the current directory), and volumes to mount the project directory inside the php container, ensuring changes to the code are immediately reflected in the container.

We also configure the MySQL service with environment variables for the root password, database name, user, and password. The volumes section ensures persistent data storage for the MySQL database by mounting a volume named db_data.

6. Running Symfony with Docker Compose

With the Docker Compose configuration in place, starting and running your Symfony application is a breeze.

6.1 Launching Containers

To launch the Symfony application and the database service, execute the following command in your Symfony project’s root directory:

bash
docker-compose up -d

The -d flag runs the containers in the background.

6.2 Accessing Symfony Application

Once the containers are up and running, you can access your Symfony application by opening a web browser and navigating to http://localhost:9000.

7. Handling Environment-specific Configuration

Symfony applications often require different configurations based on the environment (e.g., development, staging, production). Docker allows us to manage these configurations conveniently.

7.1 Environment Variables

Docker Compose allows us to define environment variables that can be used in our Symfony application. For instance, we can set environment-specific database credentials using environment variables in the docker-compose.yml file:

yaml
...
services:
  php:
    ...
    environment:
      APP_ENV: dev
      DATABASE_URL: "mysql://symfony_user:symfony_password@db/symfony_db"
…

Here, we set the APP_ENV environment variable to dev to indicate that it’s the development environment. The DATABASE_URL variable points to the MySQL database service defined in the same docker-compose.yml file.

7.2 Environment-specific Configuration Files

Additionally, you can use Symfony’s built-in environment-specific configuration files to manage different settings for each environment. For example, create a .env.dev file in the Symfony project’s root directory to override configuration settings for the development environment:

bash
# .env.dev
APP_ENV=dev
DATABASE_URL=mysql://symfony_user:symfony_password@db/symfony_db

Then, update the docker-compose.yml file to load the appropriate environment file based on the APP_ENV environment variable:

yaml
...
services:
  php:
    ...
    environment:
      APP_ENV: dev
      SYMFONY_DOTENV_VARS: APP_ENV
…

By setting SYMFONY_DOTENV_VARS to APP_ENV, Symfony will load the environment variables from the appropriate .env file based on the value of APP_ENV.

8. Connecting Symfony to a Database Container

In the previous steps, we set up a MySQL database container alongside the Symfony application container. Now, let’s configure Symfony to connect to this database.

8.1 Adding Database Service to Docker Compose

To ensure Symfony can communicate with the database container, we must define a network in the docker-compose.yml file and attach both services to it:

yaml
version: '3.8'

services:
  php:
    build: .
    container_name: my_symfony_app
    volumes:
      - .:/var/www/html
    ports:
      - "9000:9000"
    depends_on:
      - db
    environment:
      APP_ENV: dev
      SYMFONY_DOTENV_VARS: APP_ENV
    networks:
      - symfony_net

  db:
    image: mysql:5.7
    container_name: my_symfony_db
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: symfony_db
      MYSQL_USER: symfony_user
      MYSQL_PASSWORD: symfony_password
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - symfony_net

networks:
  symfony_net:
    driver: bridge

volumes:
  db_data:

In this updated docker-compose.yml file, we create a custom network called symfony_net. Both the php and db services are attached to this network using the networks directive. This allows them to communicate with each other using their service names as hostnames.

8.2 Configuring Symfony for Database Connection

Next, we need to update Symfony’s database configuration to use the database container. In the config/packages/doctrine.yaml file, configure the database connection as follows:

yaml
doctrine:
    dbal:
        driver: pdo_mysql
        url: '%env(resolve:DATABASE_URL)%'

By using the %env(resolve:DATABASE_URL)% placeholder, Symfony will fetch the value of the DATABASE_URL environment variable from the container’s environment.

With this configuration, Symfony should now be able to connect to the MySQL database running in the separate db container.

9. Using Docker Volumes for Data Persistence

Data persistence is essential for maintaining the state of your Symfony application across container restarts or updates. Docker volumes enable you to manage persistent storage for your application.

9.1 Managing Data with Volumes

In our docker-compose.yml file, we already defined a volume named db_data for the MySQL container. This volume allows the database data to persist even if the container is removed or replaced.

Docker volumes can also be used to manage other types of data, such as Symfony’s cache, logs, and uploaded files. To set up a volume for Symfony’s cache, we can modify the docker-compose.yml file:

yaml
version: '3.8'

services:
  php:
    build: .
    container_name: my_symfony_app
    volumes:
      - .:/var/www/html
      - symfony_cache:/var/www/html/var/cache
    ports:
      - "9000:9000"
    depends_on:
      - db
    environment:
      APP_ENV: dev
      SYMFONY_DOTENV_VARS: APP_ENV
    networks:
      - symfony_net

  db:
    image: mysql:5.7
    container_name: my_symfony_db
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: symfony_db
      MYSQL_USER: symfony_user
      MYSQL_PASSWORD: symfony_password
    volumes:
      - db_data:/var/lib/mysql
    networks:
      - symfony_net

networks:
  symfony_net:
    driver: bridge

volumes:
  db_data:
  symfony_cache:

In this updated configuration, we added a volume named symfony_cache, which maps the var/cache directory in the Symfony container. This ensures that the cache persists even when the container is rebuilt or recreated.

10. Scaling Symfony Containers

One of the significant advantages of using Docker is the ability to scale applications easily. Docker Swarm, a native clustering and orchestration solution for Docker, allows us to scale our Symfony containers efficiently.

10.1 Load Balancing with Docker Swarm

Docker Swarm can load balance incoming requests across multiple replicas of a service. To create a Swarm cluster and deploy our Symfony application with multiple replicas, follow these steps:

Initialize Docker Swarm on your host:

bash
docker swarm init

Deploy the Symfony service with multiple replicas:

bash
docker stack deploy -c docker-compose.yml my_symfony_stack

With this command, Docker Swarm will deploy the services defined in the docker-compose.yml file as a stack named my_symfony_stack.

10.2 Scaling Symfony Services

Now that the Symfony application is running as a stack in Docker Swarm, you can scale the number of containers to handle higher traffic:

bash
docker service scale my_symfony_stack_php=3

This command scales the number of replicas of the php service to three. Docker Swarm will distribute incoming requests evenly among the three replicas, allowing you to handle more concurrent users.

11. Debugging Symfony in Docker

When working with a Symfony application in Docker containers, debugging can be challenging. However, with a few additional configurations, we can enable and access Symfony’s debug information.

11.1 Enabling Debugging

To enable debugging, we need to set the APP_DEBUG environment variable to 1 in the docker-compose.yml file:

yaml
...
services:
  php:
    ...
    environment:
      APP_ENV: dev
      APP_DEBUG: 1
      SYMFONY_DOTENV_VARS: APP_ENV
…

By setting APP_DEBUG to 1, Symfony will display detailed error messages and stack traces for debugging purposes.

11.2 Accessing Symfony Logs

In a development environment, you can access Symfony logs directly from the container. First, identify the container ID or name using the docker ps command:

bash
docker ps

Then, use the docker logs command to access the Symfony logs:

bash
docker logs my_symfony_app

Replace my_symfony_app with your Symfony container’s ID or name.

Conclusion

Containerization with Docker offers an efficient and scalable solution for running Symfony applications. By following the steps outlined in this blog, you can successfully containerize your Symfony project, leading to easier deployments, consistent development environments, and better management of dependencies.

Remember, Docker provides numerous additional features to explore, such as container orchestration, container registries, and container monitoring. Experiment with Docker and Symfony to discover how you can enhance your application development workflow and deployment process.

Containerization with Docker and Symfony is a powerful combination that empowers developers to build robust, scalable, and portable applications with ease. Embrace containerization, and you’ll unlock the potential for smoother and more efficient application development and deployment. Happy containerizing!

Previously at
Flag Argentina
Colombia
time icon
GMT-5
Experienced in Symfony framework for robust web solutions with 5 years Symfony expertise. Proficient in back-end development, module creation, and leading teams.