Web hints Navbar toggle

Install Symfony in a Docker environment

Docker has been a very usefull tool for me and my team, you know why? Every development environment is the same, and we can tune the development environment to be close or as the same as the production environment.

Install Docker

Depending on your OS Docker has different installation methods. You can visit Docker's website for installation instructions.

During the setup of Docker, make sure you assign enough RAM and CPU power to your containers, it will heavily impact performance.

Ontwerp zonder titel (3).png

Visualisation of the architecture

As described in the infographic above, Docker is the bridge between your host system (Windows, MacOS or Linux) and your web services (Apache & MySQL server). In the Docker configuration, which is next you'll see we can forwards ports like you would on your router to access both the Apache and the MySQL server from your host machine.

The important part you need to understand is that the Apache server and MySQL server are two seperate containers, running on a single host machine.

The Docker setup

In this example I will use my already created Docker image, but you can use any Docker image that suits your needs. The data and documentation on my Docker image you can find by clicking the link.

We will use this image in our docker-compose.yml file, we can re-use this in all of our projects.

Initial docker.compose.yml

version: '3.1'
services:
  app:
    image: ciryk/dev:7.3-apache
    depends_on:
      - db
  db:
    image: mysql:5.6
    environment:
        MYSQL_DATABASE: sulu
        MYSQL_ROOT_PASSWORD: sulu

Here you can already spot the architecture we described in the infographic, two containers called app and db, each with their own specific image. The app container uses the custom image I provided you already, the database will use the mysql image, the version provided is now 5.6, but as you already might have figure out this can be changed to f.e. 5.7 or even MariaDB.

There are two requirements for your MySQL image, that is to set the database and root password being used, these credentials will be used when connecting your Symfony app with your MySQL docker container.

You can actually already start your docker containers using docker-compose up -d command in the root of your project, though this makes no sense at the moment as no ports are being forwarded to your containers.

 #...
  app:
    image: ciryk/dev:7.3-apache
    ports: 
      - "80:80"
    volumes:
     - ./app:/var/www/html
  db:
    image: mysql:5.7
    ports:
      - "3306:3306"
    volumes:
      - my-db:/var/lib/mysql
    #...
volumes:
  my-db:

Execute docker-compose up -d again to restart your containers and forward the ports provided in your configuration.

Go and visit http://localhost, you should already see an Apache error showing up, this means the Apache server is working but there's not content available yet.

Same goes for the MySQL server, connect to the container with your preferred MySQL client with the configured credentials.

Let's explain the docker-compose.yml file:

  • The ports are straightforward, when your visit port 80 on your host machine it will be forwarded to port 80 in your docker container, same for the db container
  • The volume in the app will sync all files in your app folder with your Docker container
  • The volume on the db container is a bit special, actually when using your db container without a volume attached to /var/lib/mysql your data will not be persistent, meaning on reboot of your container all data is lost, so this step is important. It's synced with an internal Docker volume, data inside this container only gets removed if the volume is removed specifically.

Install Symfony in your Docker environment

Now that your docker containers are started, go have a quick look at their status using docker ps. Both you app and db container should be running to proceed with the next steps.

> docker ps
CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                               NAMES
ce23da88c47a        ciryk/dev:7.3-apache   "docker-php-entrypoi…"   20 seconds ago      Up 19 seconds       0.0.0.0:80->80/tcp                  symfony-docker_app_1
5bef09f1bf3e        mysql:5.7              "docker-entrypoint.s…"   20 seconds ago      Up 20 seconds       0.0.0.0:3306->3306/tcp, 33060/tcp   symfony-docker_db_1

As you can see, both of my containers are up and running, and the ports are forwarded correctly.

To now start adding code, bash inside your container with docker exec -it symfony-docker_app_1 bash, this should take your to /var/www/html inside your container. Let's clone Symfony inside that root directory.

git clone https://github.com/symfony/skeleton .

Checkout to the latest release to be sure you're not working on an unstable installation:

git checkout v5.0.99

Now look at the files on your host file, you will see the app folder being populated with the skeleton files. The next step is to install your PHP dependencies using composer, again inside your docker container execute the following:

composer install

Want to see something cool? Visit http://localhost and see what shows up ;-) (You should see Symfony welcome page)

Connect your Symfony app with the DB container

So you now have:

  • A working Symfony application inside an apache container
  • A running database container

Let's combine the two!

Inside your app container, install doctrine:

composer req orm

This command will install all ORM tools for your Symfony application, now add a .env.local to the root of your app folder with the following contents:

APP_ENV=dev
DATABASE_URL=mysql://root:[email protected]:3306/symfony?serverVersion=5.7

Let's explain this DATABASE_URL, i usually copy it from .env file and change it up, it originally looks like this: DATABASE_URL=mysql://db_user:[email protected]:3306/db_name?serverVersion=5.7.

All the details that need to be filled in here is already defined in our docker-compose.yml file. Go have a look, we have MYSQL_ROOT_PASSWORD, MYSQL_DATABASE, the hostname is a Docker special. Docker uses internal networking so you can actually access your database by using the container name, which is "db".

Let's test this by creating a Entity and creating the database structure straight from the Symfony app.

Create a new file Event.php inside src/Entity:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="event")
 */
class Event
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="datetime")
     */
    private $date;

    /**
     * @ORM\Column(type="string")
     */
    private $title;

    public function getId()
    {
        return $this->id;
    }

    public function getDate()
    {
        return $this->date;
    }

    public function setDate($date): void
    {
        $this->date = $date;
    }

    public function getTitle()
    {
        return $this->title;
    }

    public function setTitle($title): void
    {
        $this->title = $title;
    }
}

This should suffice, now update your database with this new entity!

php bin/console doctrine:schema:update -f
[email protected]:/var/www/html# php bin/console doctrine:schema:update -f

 Updating database schema...

     1 query was executed


 [OK] Database schema updated successfully!

Now have a look at your database with your favourite database tool, neat huh?!

Conclusion

So what did we do here? 

  • Setup of docker-compose.yml file
  • Installation of Symfony application
  • Connect Symfony application to the MySQL Docker container

You can now start developing your application, to stop your containers your can use docker-compose down, to restart them use docker-compose up -d.

Have any questions regarding Docker in development? Feel free to comment below and I will try to help you out!