Docker PHP Nginx MySQL XDebug Entwicklungsumgebung

0
267

Bisher habe ich meine PHP-Entwicklungen mit Mamp Pro für Mac umgesetzt. Da wir beruflich schon seit ca. 1 Jahr auf Docker setzen, allerdings mit einem MSSQL DB Backend, möchte ich auch meine lokale Umgebung umstellen.

Dabei stand für mich folgendes im Vordergrund:

  • Aktuelle PHP Version (7.4)
    • Logs und Configs sollen beim Build Vorgang eingebunden / kopiert werden und jederzeit in meiner IDE abrufbar sein (gelinkt)
  • Aktuelle MySQL Version (5.4)
    • Die Datenbanken sollen allerdings auf meinem Client gespeichert und im Docker Container nur verlinkt sein
    • Es soll die Möglichkeit vorhanden sein, automatisiert beim Build Vorgang, SQL Scripte auszuführen
  • Nginx als schnelle Alternative zum Apache
  • XDebug für PHPStorm einbinden
  • sehr flexibel einstellbar

Auf meiner Suche nach einer geeigneten Docker-Umgebung habe ich zahlreiche Tutorials gefunden. Allerdings hat keines mein Vorhaben in Gänze abgedeckt – sondern bezogen sich zum einen auf ältere PHP5 Versionen, zum anderen wurde beispielsweise XDebug vernachlässigt.

Daher möchte ich hier meine Konfiguration aufzeigen – und bin für weitere Verbesserungen / Anregungen wie immer sehr dankbar.

Wichtig: Bitte entfernt die Kommentare # File! Sie dienen lediglich für Euch zur Info, wo die Datei liegen soll.

 1. Meine Ordnerstruktur

Erklärung hierzu:

Das Hauptverzeichnis lautet: Docker_Noobis_Tutorial

In diesem befindet sich der Ordner docker (der die Docker Konfigurationen beinhaltet) sowie den Ordner dockerlive. Letzterer beinhaltet die aktuellen LOG Files sowie die MySQL Datenbanken.

Im Ordner php-app habe ich dann letztendlich meine PHP-Anwendung hinterlegt.

 

 2. Die Konfigurationsdateien im Detail: Datenbank Konfiguration

Im Ordner database befindet sich der Ordner „sql-init-scripts“ mit der Datei init.sql. Hier können Statements hinterlegt werden, die beim Build Prozess direkt ausgeführt werden. Beispielsweise die Anlage einer Tabelle oder Inhalte. Aktuell ist diese Datei noch leer.

Meine Dockerfile sieht wie folgt aus:

# File: docker/database/Dockerfile
FROM mysql:latest                          # Aktueller MySQL Server
RUN apt-get update -y                      # Aktualisierungen durchführen
ENV MYSQL_DATABASE dev_db                  # Datenbank, hier dev_db
ENV MYSQL_ROOT_PASSWORD SECURE_PASSWORD    # Passwort

# Kopieren der Init Scripte zwecks Ausführung
COPY ./sql-init-scripts/ /docker-entrypoint-initdb.d/

3. Die Konfigurationsdateien im Detail: Nginx Konfiguration

Im Ordner nginx sind nun die Konfigurationen für den Nginx Webserver abgelegt:

# File: docker/nginx/sites-enabled-localhost.conf

server {
    server_name localhost;
    root /var/www;

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

    location ~ ^/index\.php(/|$) {

            fastcgi_pass php:9000;
            fastcgi_buffers 16 16k;
            fastcgi_buffer_size 32k;
            include fastcgi_params;
            #fastcgi_param SCRIPT_FILENAME /var/www/index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
     }

    location ~ \.php$ {
        return 404;
    }
    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
}
# File docker/nginx/nginx.conf

user www-data;
pid /run/nginx.pid;
worker_processes  1;
daemon off;
events {
        worker_connections 768;
        # multi_accept on;
}
http {
        client_max_body_size 20M;
        ##
        # Basic Settings
        ##
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        # server_tokens off;
        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ##
        # SSL Settings
        ##
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;
        ##
        # Logging Settings
        ##
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        ##
        # Gzip Settings
        ##
        gzip on;
        gzip_disable "msie6";
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        ##
        # Virtual Host Configs
        ##
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}
# File: docker/nginx/Dockerfile
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y nginx nano
COPY nginx.conf /etc/nginx/nginx.conf
ADD sites-enabled /etc/nginx/sites-enabled
RUN rm /etc/nginx/sites-enabled/default
WORKDIR /var/www
CMD ["nginx"]

4. Die Konfigurationsdateien im Detail: PHP 7.4 Konfiguration

Mittels dieser Konfiguration können alle PHP7.x Versionen installiert werden. Ich habe hier die Version 7.4 verwendet.

Zwecks Übersicht, habe ich diese euch hier verlinkt: php.ini 
(Es handelt sich um die originale PHP 7.4.4 INI, gespeichert wird diese unter docker/php74/conf/php.ini)
# File docker/php74/conf/php-fpm.conf

[global]
pid = /run/php/php7.4-fpm.pid
error_log = /var/log/php7.4-fpm.log
daemonize = no
include=/etc/php/7.4/fpm/pool.d/*.conf
# File docker/php74/conf/www.conf

[www]
user = www-data
group = www-data
listen = 0.0.0.0:9000
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chdir = /
# File docker/php74/Dockerfile

FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -y

RUN apt -y install software-properties-common
RUN add-apt-repository ppa:ondrej/php
RUN apt-get update

RUN apt-get install -y \
  nano \
  curl \
  wget \
  php-curl \
  php-fpm \
  php-gd \
  php7.4-xsl \
  php7.4-mysqlnd \
  php-cli \
  php-intl \
  php-bz2 \
  php-zip \
  php-mbstring \
  git \
  zip \
  php-apcu \
  php7.4-opcache \
  php-xdebug

RUN mkdir /run/php
ADD conf/www.conf /etc/php/7.4/fpm/pool.d/www.conf
ADD conf/php-fpm.conf /etc/php/7.4/fpm/php-fpm.conf
ADD conf/php.ini /etc/php/7.4/fpm/php.ini
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
RUN php composer-setup.php
RUN php -r "unlink('composer-setup.php');"
RUN mv composer.phar /usr/local/bin/composer
RUN chmod +x /usr/local/bin/composer
RUN ln -snf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
RUN echo "xdebug.idekey = PHPSTORM" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini
RUN echo "xdebug.default_enable=1" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini
RUN echo "xdebug.remote_enable=1" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini
RUN echo "xdebug.remote_autostart = 1" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini
RUN echo "xdebug.remote_port = 9001" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini
RUN echo "xdebug.remote_handler = dbgp" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini
RUN echo "xdebug.remote_host = $(getent hosts docker.for.mac.localhost | awk '{ print $1 }')" >> /etc/php/7.4/fpm/conf.d/20-xdebug.ini

WORKDIR /var/www
CMD ["php-fpm7.4"]

 5. Die Konfigurationsdateien im Detail: Die Docker-compose.yml

Diese Datei ist für den letztendlichen Build verantwortlich.

# File: docker/docker-compose.yml

version: '3'
services:
  php:
    build: docker/php74
    expose:
      - '9000'
    depends_on:
      - db
    volumes:
      - ./php-app:/var/www
      - ./dockerlive/logs:/var/log

  nginx:
    build: docker/nginx
    restart: always
    expose:
      - '80'
    ports:
      - '80:80'
    depends_on:
      - php
      - db
    volumes:
      - ./php-app:/var/www
      - ./dockerlive/logs:/var/log/nginx

  db:
    build: docker/database
    restart: on-failure
    ports:
      - "3306:3306"
    volumes:
      - ./dockerlive/mysql:/var/lib/mysql

 6. Ein paar Zusatzinformationen

Bewusst bin ich bei den Konfigurationsdateien nicht ins Detail eingegangen – da ein Grundverständnis für Docker auf anderen Seiten / Plattformen gut erklärt wird.

Ich habe mein php-app direkt in das Serververzeichnis var/www verlinkt. Wenn man z. B. CodeIgniter oder Laravel einsetzen möchte, müssen die Pfade angepasst werden.

Wenn Konfigurationsdateien angepasst werden, reicht es in diesem Fall nicht aus, die Container neu zu starten! Hintergrund ist, das wir beim Build Prozess die Dateien immer (siehe jeweilige Dockerfiles) in den Container kopieren.

Starten kann man das ganze mit:

docker-compose up --build

Aktuell bereit ich Teil 2 vor. im zweiten Teil des Tutorials möchte ich dann gezielt auf die Einrichtung von PHPStorm und Docker eingehen, sowie der Einrichtung von XDebug. Dies hätte den aktuellen Beitrag gesprengt.

Hier könnt ihr das Projekt auch per ZIP File herunterladen: Noobis_Tutorial_Docker.zip

Alternativ kann hier eine PHP7.4 Version (Achtung: DB Passwort hat sich geändert) bezogen werden: docker_container.zip

Wie immer bin ich für Anregungen / Verbesserungen aber auch Kritik sehr dankbar. Schreibt es mir doch in die Kommentare.