docker-compose 你的整个 Laravel + Apache + MySQL 开发环境。
ls 引导/缓存-al
内容
简介
当招募新开发者加入项目贡献时,你可能不希望他们花费数小时在文档和 StackOverflow 之间来回切换,摸索着如何让一切正常运行。为了让应用版本在本地运行,他们可能需要处理很多事情:php、ini 配置、php 扩展、apache 配置、apache 站点启用配置、设置 mysql 等等。除非你已经docker
搭建好了环境,这样他们就可以简单地:
$ git clone git@git.repo.url/laravel-project
$ cd laravel-project
$ docker-compose up
并能够从composer
、开始php artisan
并编写一些代码。
设置
为了演示现有的 Laravel 应用程序,我将使用从https://github.com/laravel/laravel.git克隆的空白 Laravel 应用程序
$ git clone https://github.com/laravel/laravel.git
$ cd laravel
$ git checkout -b dev-env
$ cp .env.example .env
以下是我构建 docker 环境文件的方式:
app
|__bootstrap
|__config
|__database
|__public
|__resources
|__routes
|__run (+)
|__.gitkeep (+)
|__storage
|__tests
.dockerignore (+)
.editorconfig
.env
.env.example
.gitattributes
.gitignore
artisan
CHANGELOG.md
composer.json
docker-compose.yml (+)
Dockerfile (+)
package.json
phpunit.xml
readme.md
server.php
webpack.mix.js
docker-compose
我们的想法是,我们将从主应用程序文件夹构建镜像并运行命令,而run
文件夹包含开发所需的配置和本地数据库。使用docker
卷,我们可以将源代码、vendor
依赖项和本地开发数据库保存在主机中,而所有运行时(apache
, php
)都由容器保存和管理。
在本文中,我将尽我所知解释该设置的每个部分的作用。如果您只需要一个可用的版本,请在 TL;DR 以及 GitHub 链接中列出底部的所有更改。
Laravel 的 Web 服务器映像
php-apache:7.2
来自 php dockerhub 的图片包含一个开箱即用的、可配置且功能齐全的 Apache Web 服务器mod_php
,它运行在 上,非常适合入门。我们需要一些扩展和访问控制配置来简化开发(可选)。具体如下Dockerfile
:
FROM php:7.2-apache
RUN apt-get update
# 1. development packages
RUN apt-get install -y \
git \
zip \
curl \
sudo \
unzip \
libicu-dev \
libbz2-dev \
libpng-dev \
libjpeg-dev \
libmcrypt-dev \
libreadline-dev \
libfreetype6-dev \
g++
# 2. apache configs + document root
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# 3. mod_rewrite for URL rewrite and mod_headers for .htaccess extra headers like Access-Control-Allow-Origin-
RUN a2enmod rewrite headers
# 4. start with base php config, then add extensions
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
RUN docker-php-ext-install \
bz2 \
intl \
iconv \
bcmath \
opcache \
calendar \
mbstring \
pdo_mysql \
zip
# 5. composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# 6. we need a user with the same UID/GID with host user
# so when we execute CLI commands, all the host file's ownership remains intact
# otherwise command from inside container will create root-owned files and directories
ARG uid
RUN useradd -G www-data,root -u $uid -d /home/devuser devuser
RUN mkdir -p /home/devuser/.composer && \
chown -R devuser:devuser /home/devuser
从 Web 服务器本身开始,php-apache
默认情况下将文档根目录设置为/var/www/html
。但是,由于 Laravelindex.php
位于 中/var/www/html/public
,我们需要编辑 Apache 配置以及 sites-available 。我们还将启用mod_rewrite
URL 匹配和mod_headers
配置 Web 服务器标头。
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
进入php
配置阶段,我们首先使用提供的配置php.ini
,然后通过 添加几个扩展docker-php-ext-install
。这些任务的执行顺序并不重要(php.ini
不会被覆盖),因为加载每个扩展的配置都保存在单独的文件中。
对于composer
,我们在这里做的是从Docker 镜像中获取composer
位于 的二进制文件。当然,您可以在标签中指定任何其他版本,而不是。这是 Docker 多阶段构建功能的一部分。/usr/bin/composer
composer:latest
latest
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
最后的步骤是可选的。由于我们要将应用程序源代码从主机挂载到容器中进行开发,因此在容器 CLI 中运行的任何命令都不应影响主机文件/文件夹的所有权。这对于生成的配置等信息很有帮助php artisan
。在这里,我使用ARG
让其他团队成员设置uid
与主机用户匹配的配置uid
。
ARG uid
RUN useradd -G www-data,root -u $uid -d /home/devuser devuser
RUN mkdir -p /home/devuser/.composer && \
chown -R devuser:devuser /home/devuser
docker-compose.yml
Web 服务器已设置完毕。现在我们只需要使用docker-compose
配置引入数据库容器
docker-compose.yml
version: '3.5'
services:
laravel-app:
build:
context: '.'
args:
uid: ${UID}
container_name: laravel-app
environment:
- APACHE_RUN_USER=#${UID}
- APACHE_RUN_GROUP=#${UID}
volumes:
- .:/var/www/html
ports:
- 8000:80
networks:
backend:
aliases:
- laravel-app
mysql-db:
image: mysql:5.7
container_name: mysql-db
volumes:
- ./run/var:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=securerootpassword
- MYSQL_DATABASE=db
- MYSQL_USER=dbuser
- MYSQL_PASSWORD=secret
networks:
backend:
aliases:
- db
networks:
backend:
name: backend-network
这里有几件事需要注意。首先是 Laravel 容器:
build:context
指的是Dockerfile
我们刚刚编写的,与保存在同一个目录中docker-compose.yml
。args
就是uid
我上面提到的那个。我们会UID
在应用.env
文件中写入值,以便我们docker-compose
获取它。
.env
...
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
UID=1000
APACHE_RUN_USER
并且APACHE_RUN_GROUP
ENV 变量是自带的php-apache
。这样,Web 服务器生成的文件也将具有一致的所有权。volumes
指令指示docker
将主机的应用程序源代码挂载到/var/www/html
- 这与配置一致apache
。这使得主机文件的任何更改都能反映在容器中。诸如composer require
将添加vendor
到主机的命令,因此我们无需在每次容器关闭和重新启动时安装依赖项。- 但是,如果您要为 CI/远程虚拟机环境构建容器,则需要将源文件添加到容器预构建中。例如:“Dockerfile”
复制 . /var/www/html
运行 cd /var/www/html && composer install && php artisan key:generate
- `ports` is optional, leave out if you're fine with running it under port 80. Alternatively, it can be configurable using `.env` similar to build args:
```yaml
ports:
- ${HOST_PORT}:80
HOST_PORT=8080
networks
也是aliases
可选的。默认情况下,docker-compose
创建一个default
以父文件夹名称为前缀的网络,以连接 中指定的所有服务docker-compose.yml
。但是,如果您有多个开发项目docker-compose
,networks
则像这样指定名称允许您从其他docker-compose.yml
文件加入它。another-app
在这里,使用指定的 ,您将能够到达laravel-app
,反之亦然aliases
。
docker-compose.yml
services:
another-app:
networks:
backend:
aliases:
- another-app
networks:
backend:
external:
name: backend-network
现在转到mysql
:
mysql:5.7
它配置性极高,开箱即用。所以我们不需要扩展它。- 只需在 laravel 应用程序中选择设置
.env
数据库用户的用户名和密码:```yaml
环境:
- MYSQL_ROOT_PASSWORD=安全根密码
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
- Also make sure `.env DB_HOST` set to what mysql-db service name, or its aliases:
`.env`
DB_HOST=mysql-db
- Ideally you want to keep database changes in the repository, using a series of migrations and seeders. However if you want to start the mysql container with an existing SQL dump, simply mount the SQL file:
```yaml
volumes:
- ./run/var:/var/lib/mysql
- ./run/dump/init.sql:/docker-entrypoint-initdb.d/init.sql
- 使用
volumes
,我们将数据库本地保存在 下run/var
,因为任何由 写入的数据mysqld
都在容器的 内。我们只需要在 和中/var/lib/mysql
忽略本地数据库(对于构建上下文):.gitignore
.dockerignore
.gitignore
:
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
.env
.phpunit.result.cache
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
run/var
.dockerignore
:
run/var
启动并运行
现在让我们构建环境并运行它。我们还将安装 Composer 依赖项以及一些 Artisan 命令。
$ docker-compose build && docker-compose up -d && docker-compose logs -f
Creating network "backend-network" with the default driver
Creating mysql-db ... done
Creating laravel-app ... done
Attaching to laravel-app, mysql-db
...
一旦所有容器都启动并运行,我们可以通过以下方式检查它们docker ps
:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c1ae3002d260 laravel_laravel-app "docker-php-entrypoi…" 4 minutes ago Up 4 minutes 0.0.0.0:8000->80/tcp laravel-app
6f6546224051 mysql:5.7 "docker-entrypoint.s…" 4 minutes ago Up 4 minutes 3306/tcp mysql-db
作曲家和工匠:
$ docker exec -it laravel-app bash -c "sudo -u devuser /bin/bash"
devuser@c1ae3002d260:/var/www/html$ composer install
...
Generating optimized autoload files
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
devuser@c1ae3002d260:/var/www/html$ php artisan key:generate
Application key set successfully.
devuser@c1ae3002d260:/var/www/html$ php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table
devuser@c1ae3002d260:/var/www/html$ php artisan make:auth
Authentication scaffolding generated successfully.
使用主机文件:
127.0.0.1 laravel-app.local
帮助脚本(可选)
有时,我希望能够快速运行 CLI 命令(composer
例如artisan
、 等等),而不必每次都手动输入docker exec
。因此,以下是我编写的一些围绕 的 bash 脚本docker exec
:
container
#!/bin/bash
docker exec -it laravel-app bash -c "sudo -u devuser /bin/bash"
运行./container
将带您进入laravel-app
用户下的容器uid(1000)
(与主机用户相同)
$ ./container
devuser@8cf37a093502:/var/www/html$
db
#!/bin/bash
docker exec -it mysql-db bash -c "mysql -u dbuser -psecret db"
运行./db
将使用 mysql 客户端连接到数据库容器的守护进程。
$ ./db
mysql>
composer
#!/bin/bash
args="$@"
command="composer $args"
echo "$command"
docker exec -it laravel-app bash -c "sudo -u devuser /bin/bash -c \"$command\""
运行任意composer
命令,例如:
$ ./composer dump-autoload
Generating optimized autoload files> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: fideloper/proxy
Discovered Package: laravel/tinker
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Package manifest generated successfully.
Generated optimized autoload files containing 3527 classes
php-artisan
#!/bin/bash
args="$@"
command="php artisan $args"
echo "$command"
docker exec -it laravel-app bash -c "sudo -u devuser /bin/bash -c \"$command\""
运行php artisan
命令,例如:
$ ./php-artisan make:controller BlogPostController --resource
php artisan make:controller BlogPostController --resource
Controller created successfully.
phpunit
#!/bin/bash
args="$@"
command="vendor/bin/phpunit $args"
echo "$command"
docker exec -it laravel-app bash -c "sudo -u devuser /bin/bash -c \"$command\""
运行./vendor/bin/phpunit
执行测试,例如:
$ ./phpunit --group=failing
vendor/bin/phpunit --group=failing
PHPUnit 7.5.8 by Sebastian Bergmann and contributors.
Time: 34 ms, Memory: 6.00 MB
No tests executed!
TL;DR
链接:
Dockerfile
由基本的 apache 文档根配置、mod_rewrite 和 mod_header、作曲家和同步容器的 uid 与主机 uid 组成。
docker-compose.yml
启动php-apache
(挂载应用程序文件)和mysql
(挂载数据库文件),用于networks
互连。
使用环境:
$ docker-compose build && docker-compose up -d && docker-compose logs -f
$ ./composer install
$ ./php-artisan key:generate