https://github.com/maxyc/laravel-tickets/blob/master/docker-compose.yml
Данная конфигурация кочует со мной из проекта в проект
Первым делом давайте разберемся: какие сервисы нам потреубуются?
- php-fpm 7.4+ with xdebug
- mysql | postgresql | sqlite
- nginx | apache
- redis | … etc…
Давайте попробуем на примере php-fpm 7.4 + mysql + nginx
Создадим папку нашего проекта /var/www/example.loc/
и создадим в ней файл docker-compose.yml
, также нам понадобится папка ./docker
где будем хранить конфигурации наших сервисов.
Внутренняя сеть
В нашей сборке ничего, кроме nginx не будет смотреть наружу. Ни какие порты, кроме 80. Нам не требуется извне иметь доступ к 9000 порту php или 3306 бд. Все контейнеры будут залинкованы между собой внутренней сетью, которую можно описать следующим образом:
networks: internal: driver: bridge ipam: driver: default config: - subnet: 192.168.220.0/28
База данных
db:
image: mysql
restart: always
command: --default-authentication-plugin=mysql_native_password
networks:
- internal
environment:
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
- MYSQL_ROOT_PASSWORD=${DB_PASSWORD}
volumes:
- ./docker/mysql/datadir:/var/lib/mysql
Нам необходимо в корне папки создать файл .env, в котором будут наши настройки БД
DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=db DB_USERNAME=user DB_PASSWORD=123456
Эти данные в дальнейшем будут в .env
файле нашего проекта на Laravel.
Стоит обратить внимание на DB_HOST=db
. Здесь нельзя указывать localhost
или еще какой ip. За счет удобной внутренней сети докера мы можем использовать имя сервиса в качестве пути к серверу базы данных. в нашем случае это db
Т.к. после перезапуска контейнера все данные удаляются, то нам необходимо вынести файлы таблиц базы данных. Поэтому помещаем их в папку docker/mysql
volumes:
- ./docker/mysql/datadir:/var/lib/mysql
Если вдруг вам потребуется mariadb, то вместо image: mysql
, впишите image: mariadb
. Конфигурация остается та же.
А что, если мы захотим использовать postgresql? Все так же просто:
db: image: postgres restart: always networks: - internal environment: - POSTGRES_DB=${DB_DATABASE} - POSTGRES_USER=${DB_USERNAME} - POSTGRES_PASSWORD=${DB_PASSWORD} volumes: - ./docker/postgres/datadir:/var/lib/postgresql/data
С базами данных закончили.
php-fpm
Будем использовать кастомную сборку php-fpm
, т.к. нам необходимо добавить поддержку работы с базой данных, поддержку xdebug и пр.
Для начала опишем сервис. Условимся, что наш docker-compose.yml
и папка docker
будет лежать в корне laravel
проекта на одном уровне с папкой app
php-fpm: build: context: docker/php-fpm volumes: - ./:/var/www environment: XDEBUG_CONFIG: "remote_host=192.168.220.1 remote_enable=1" PHP_IDE_CONFIG: "serverName=Docker" depends_on: - db networks: - internal
Т.к. наша сборка кастомная, то вместо image
секции, нам необходимо указать путь к настройкам:
build:
context: docker/php-fpm
Создаем папку ./docker/php-fpm
и в ней два файла php.ini
и Dockerfile
, в котором далее будем описывать процесс сборки php-fpm
В php.ini мы можем указать желаемые нами параметры, например:
max_execution_time = 1000 max_input_time = 1000 error_reporting=E_ALL display_errors=on short_open_tags=off
Перейдем к Dockerfile. В этом файле (с большой буквы) хранятся построчно все инструкции по установке php внутри контейнера.
FROM php:7.4-fpm RUN apt-get update \ && apt-get install -y wget git unzip libpq-dev libicu-dev libpng-dev libzip-dev libjpeg-dev libfreetype6-dev\ && pecl install xdebug-2.9.1 \ && docker-php-ext-enable xdebug \ && docker-php-ext-install pdo_pgsql \ && docker-php-ext-install pgsql \ && docker-php-ext-install zip \ && docker-php-ext-install gd \ && docker-php-ext-enable pgsql ADD ./php.ini /usr/local/etc/php/php.ini RUN wget https://getcomposer.org/installer -O - -q \ | php -- --install-dir=/bin --filename=composer --quiet USER 1000 WORKDIR /var/www
В первой строке (команда FROM
) мы указали какую версию image
файла нам использовать. В данном случае php:7.4-fpm
Следующая команда RUN
устанавливает требуемые зависимости
Далее, мы указываем контейнеру, что php.ini
необходимо брать из нашей текущей папки.
Далее, Устанавливаем composer
. Он нужен нам только на уровне php-fpm
контейнера.
Ну и наконец указываем контейнеру, где лежат все наши файлы со стороны контейнера. В нашем случае, мы указали, что корень нашего сервера это /var/www
Вы можете с легкостью указать любую другую версию php, например
php:7.3-fpm
, но учтите, для этой версии может потребуетсяxdebug
более низкой версии, например 2.7.1
Nginx
nginx: build: context: docker/nginx volumes: - ./:/var/www/ - ./storage/app/public/:/var/www/public/storage/ ports: - 80:80 depends_on: - php-fpm networks: - internal
Обратите внимание, что папку storage мы пробрасываем на уровне конфигурации. Симлинки не работают между контейнерами. В нашем случае nginx и php-fpm
Nginx у нас так же имеет кастомную сборку, потому указываем путь к файлу Dockerfile как в прошлом примере.
Создаем папку ./docker/nginx
и там файл Dockerfile и папку conf.d
В conf.d у нас будут храниться виртуальные хосты, обычно 1-2 достаточно. Обрабатываются только файлы с расширением .conf. Например, default.conf:
server { charset utf-8; client_max_body_size 128M; listen 80; ## listen for ipv4 server_name example.loc localhost; root /var/www/public; index index.php; location / { try_files $uri $uri/ /index.php$is_args$args; } location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass php-fpm:9000; fastcgi_index index.php; fastcgi_read_timeout 1000; #fastcgi_pass unix:/var/run/php5-fpm.sock; try_files $uri =404; #fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; } location ~* /\. { deny all; } }
Настроим Dockerfile следующим образом:
FROM nginx ADD ./conf.d /etc/nginx/conf.d/ WORKDIR /var/www
На этом настройка окружения для нашего проекта закончена. Нам остается только запустить контейнеры командой
docker-compose up -d --build
Если все ок, то наше приложение теперь доступно по адресу http://localhost
Одна из возможных причин, почему не запустилось, может крыться в том, что 80 порт может быть уже занят. В любом случае, понять причину ошибки можно запустив команду docker-compose logs и проанализировав ее.
Установка Laravel
Предположим, что мы разворачиваем фреймфорк впервые на машине, где не установлен php. Для того, чтобы установить фреймворк, нам необходимо скачать его командой
git clone https://github.com/laravel/laravel.git laravelapp
И скопировать все файлы в папке laravelapp в корень нашего сервера.
Для того, чтобы можно было использовать artisan, нам необходимо обращаться к нему внутри контейнера, а именно docker-compose exec php-fpm php artisan make:controller
, либо запускать команды внутри контейнера запустив команду docker-compose exec php-fpm bash
, а затем уже использовать php artisan make:controller
Часто у новичков и не только, у кого локально установлен php? возникает ошибка подключения к базе данных, при использовании команд artisan. Для решения которой, как бы не было это глупо и банально, предлагаю проверить как вы запускаете команду. Возможно вы запускаете ее локально, а не в контейнере. =)
Здравствуйте, что-то у меня не так
в конце выполнения docker-compose up -d –build возникают ошибки
Creating db … done
Creating php-fpm … error
ERROR: for php-fpm Cannot start service php-fpm: OCI runtime create failed: container_linux.go:345: starting container process caused “chdir to cwd (\”/var/www\”) set in config.json failed: permission denied”: unknown
ERROR: Encountered errors while bringing up the project.
Потом смотрю в portainer контейнер db вроде running, а php-fpm просто created и при попытке запуска выдаёт ту же ошибку OCI runtime create failed.
В логах db
2020-11-28 15:16:15+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.22-1debian10 started.,
2020-11-28 15:16:16+00:00 [Note] [Entrypoint]: Switching to dedicated user ‘mysql’,
2020-11-28 15:16:17+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.22-1debian10 started.,
2020-11-28 15:16:17+00:00 [Note] [Entrypoint]: Initializing database files,
mysqld: Can’t create directory ‘/var/lib/mysql/’ (OS errno 17 – File exists),
2020-11-28T15:16:17.119612Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.22) initializing of server in progress as process 43,
2020-11-28T15:16:17.120948Z 0 [ERROR] [MY-013236] [Server] The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.,
2020-11-28T15:16:17.120984Z 0 [ERROR] [MY-010119] [Server] Aborting,
2020-11-28T15:16:17.121088Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.22) MySQL Community Server – GPL.
Привет. Сложно так будет сказать что у вас. У вас что то с правами доступа.
https://youtu.be/9TlXDyoCK10
Я вот попробовал впервые видео записать. Вдруг поможет вместе со мной повторять действия
Привет.
Видео с ошибкой не помогло. Но хорошее – поставил доп компоненты
Creating cache … done
Creating db … done
Creating node … error
Creating backend … error
ERROR: for backend Cannot start service backend: OCI runtime create failed: container_linux.go:345: starting container process caused “chdir to cwd (\”/var/www\”) set in config.json failed: permission denied”: unknown
ERROR: for node Cannot start service node: OCI runtime create failed: container_linux.go:345: starting container process caused “chdir to cwd (\”/home/node/app\”) set in config.json failed: permission denied”: unknown
Похоже действительно были проблемы с правами доступа. Папка проекта выглядела вот так в листинге
drwx——+ 1 schel4ok users 556 Nov 29 20:34 example.loc
Я попробовал изменил права для юзера 1000 вот так
chown -vR 1000:1000 example.loc
chmod 700 example.loc
Теперь стало так.
drwx—— 1 1000 1000 556 Nov 29 20:34 example.loc
И после этого php стартанул. Что это за юзер 1000?
Это типа www-data? У меня просто линукс не чистый, а сборка Synology DSM. Там много изменений.
Например не работают команды make и нет юзера www-data нет, но есть юзер http. Может вместо 1000 использовать id юзера http?
В логе nginx всё ОК
/docker-entrypoint.sh: Configuration complete; ready for start up
В логе php есть вот такие строчки, которые мне не очень ясны. Вроде работает, но первые 2 строки напрягают
NOTICE: [pool www] ‘user’ directive is ignored when FPM is not running as root,
NOTICE: [pool www] ‘group’ directive is ignored when FPM is not running as root
NOTICE: fpm is running, pid 1,
NOTICE: ready to handle connections
В логе db всё ОК
LOG: database system is ready to accept connections
cache вообще никакого лога не выводит
А node какой-то странный. Он стартует, а потом автоматически останавливается со статусом Stopped for a few seconds with exit code 1.
да , нода не висит в качестве демона. в видео показал как им пользоваться. как обычной программой запускать