Nikita P
Nikita P

Reputation: 169

Docker, Symfony nginx/php-fpm initialized very slow

Using this project/Docker setup: https://gitlab.com/martinpham/symfony-5-docker

When I do docker-compose up -d I have to wait about 2-3 minutes to actually get it working. Before it loads, it gives me "502 Bad Gateway" and logs error:

2020/05/10 09:22:23 [error] 8#8: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.28.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://172.28.0.3:9000", host: "localhost"

Why nginx or php-fpm or smth else is loading so slow ? It's my first time using nginx and Symfony. Is it something normal ? I expect it to be loaded max in 1-2 second, not 2-3 minutes.

Yes, I have seen similar issues, but not appropriate solutions for me. Some nginx/php-fpm/docker-compose configuration should be changed - I tried, but no luck. I modified a little bit nginx/sites/default.conf (just added xdebug stuff)

server {
    listen 80 default_server;
    #listen [::]:80 default_server ipv6only=on;

    server_name localhost;

    root /var/www/public;
    index index.php index.html index.htm;

    location / {
         try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_pass php-upstream;
        fastcgi_index index.php;
        fastcgi_buffers 4 256k;
        fastcgi_buffer_size 128k;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        #!!!!fixes timeouts
        fastcgi_read_timeout 600;
        include fastcgi_params;

        fastcgi_param PHP_VALUE "xdebug.remote_autostart=1
        xdebug.idekey=PHPSTORM
        xdebug.remote_enable=1
        xdebug.remote_port=9001
        xdebug.remote_host=192.168.0.12";
    }

    location ~ /\.ht {
        deny all;
    }

    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt/;
        log_not_found off;
    }
}

nginx/conf.d/default.conf:

upstream php-upstream {
    server php-fpm:9000;
}

docker-compose.yml:

version: '3'

services:
  database:
    build:
      context: ./database
    environment:
      - MYSQL_DATABASE=${DATABASE_NAME}
      - MYSQL_USER=${DATABASE_USER}
      - MYSQL_PASSWORD=${DATABASE_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD}
    ports:
      - "3306:3306"
    volumes:
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
      - ./database/data:/var/lib/mysql

  php-fpm:
    build:
      context: ./php-fpm
    depends_on:
      - database
    environment:
      - TIMEZONE=Europe/Tallinn
      - APP_ENV=${APP_ENV}
      - APP_SECRET=${APP_SECRET}
      - DATABASE_URL=mysql://${DATABASE_USER}:${DATABASE_PASSWORD}@database:3306/${DATABASE_NAME}?serverVersion=5.7
    volumes:
      - ../src:/var/www

  nginx:
    build:
      context: ./nginx
    volumes:
      - ../src:/var/www
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx/sites/:/etc/nginx/sites-available
      - ./nginx/conf.d/:/etc/nginx/conf.d
      - ./logs:/var/log
    depends_on:
      - php-fpm
    ports:
      - "80:80"
      - "443:443"

Upvotes: 3

Views: 6120

Answers (1)

mxlhz
mxlhz

Reputation: 1118

EDIT:

I think I know why now your project is taking ages to start. I had a closer look at the Dockerfile in the php-fpm folder and you have that command:

CMD composer install ; wait-for-it database:3306 -- bin/console doctrine:migrations:migrate ;  php-fpm 

As you can see, that command will install all composer dependencies and then wait until it can connect to the database container defined in the docker-compose.yml configuration :

services:
  database:
    build:
      context: ./database
    environment:
      - MYSQL_DATABASE=${DATABASE_NAME}
      - MYSQL_USER=${DATABASE_USER}
      - MYSQL_PASSWORD=${DATABASE_PASSWORD}
      - MYSQL_ROOT_PASSWORD=${DATABASE_ROOT_PASSWORD}
    ports:
      - "3306:3306"
    volumes:
      - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
      - ./database/data:/var/lib/mysql

Once the database is up and running, it will run the migration files in src/src/Migrations to update the database and then start php-fpm.

Until all of this is done, your project won't be ready and you will get the nice '502 Bad Gateway' error.

You can verify this and what's happening by running docker-compose up but omitting the -d argument this time so that you don't run in detached mode, and this will display all your container logs in real time.

You will see a bunch of logs, including the ones related to what composer is doing in the background, ex:

api-app     |   - Installing ocramius/package-versions (1.8.0): Downloading (100%)         
api-app     |   - Installing symfony/flex (v1.6.3): Downloading (100%)         
api-app     | 
api-app     | Prefetching 141 packages 
api-app     |   - Downloading (100%)
api-app     | 
api-app     |   - Installing symfony/polyfill-php73 (v1.16.0): Loading from cache
api-app     |   - Installing symfony/polyfill-mbstring (v1.16.0): Loading from cache

Composer install might take more or less time depending on whether you have all the repositories cached or not.

The solution here if you want to speed things up during your development would be remove the composer install command from the Dockerfile and run it manually only when you want to update/install new dependencies. This way, you avoid composer install to be run every time you run docker-compose up -d.

To do it manually, you would need to connect to your container and then run composer install manually or if you have composer directly installed in your OS, you could simply navigate to the src folder and run that same command.

This + the trick below should help you have a nice a fast enough project locally.


I have a similar configuration and everything is working well, the command docker-compose should take some time the first time you run it as your images need to be built, but then it shouldn't even take a second to run.

From what I see however, you have a lot of mounted volumes that could affect your performances. When I ran tests with nginx and Symfony on a Mac, I had really bad performances at the beginning with pages taking at least 30 seconds load.

One solution to speed this up in my case was to use the :delegated option on some of my volumes to speed up their access.

Try adding that options to your volumes and see if it changes anything for you:

[...]
     volumes:
          - ../src:/var/www:delegated
[...]

If delegated is not good option for you, read more about the other options consistent and cached here to see what would best fits your needs.

Upvotes: 6

Related Questions