Laravel + Docker 第 1 部分-开发设置

本文共计两个部分,这是第一部分。我们将介绍如何使用 Docker 在本地运行Laravel 应用程序。 然后第 2 部分将展示如何在生产环境中运行相同的应用程序来完成本教程。

第一篇文章的目标是创建一个可复制的开发环境,该环境轻巧,快速并且不依赖于本地计算机上全局安装的任何内容(docker 本身除外)。

所以,我们将实现以下目标。

  • 不需要  Mamp 或者其他类似的程序
  • 不需要 Vagrant 或者其他类似的虚拟机
  • 不需要 全局安装的 PHP
  • 不需要 全局安装的 Composer

第1步 — 获取最新版的 Laravel

我将通过 curl 的方式来获取 github 上最新的 Laravel 代码,这样可以对获取的代码进行多份复制 — 你可以通过执行git clone 来获取 — 但是不要忘记在完成后清理 .git 文件。

这里我们不遵循 Laravel 官方指南的设置,因为我们不希望在机器上安装全局的 PHP/Composer。

curl -L <https://github.com/laravel/laravel/archive/v5.3.16.tar.gz> | tar xz

执行上面的命令将得到一个名为 laravel-5.3.16 的目录 —你应将其命名为你想要的项目名称。例如 mv laravel-5.3.16 my-site(重命名为 my-site)然后 cd 进入目录。

步骤2 — 安装依赖

我们需要运行 composer install 来提取所有组成 Laravel 的库-我们可以使用来自[docker hub]的 composer docker hub 为我们处理此问题。

我们将通过执行以下命令来创建一个一次性容器。

docker run --rm -v $(pwd):/app composer/composer install

注意:

  • 我们使用 --rm 标志确保此容器不会在安装后逗留。
  • -v $(pwd):/app 用于将主机(您的cpu)上的当前目录挂载到容器中的 /app 中 —这是在 Composer 内部运行的位置容器希望找到一个 composer.json
  • -v $(pwd):/app 还将确保由 composer 在容器内创建的vendor文件夹在我们的计算机上也可见。

步骤 3 — 创建开发文件 docker-compose.yml 

我们将使用2个单独的文件来定义环境的运行方式。一个用于开发,另一个用于生产。现在,Docker-compose 确实支持使用多个输入文件,允许您覆盖特定的键-但由于它合并数组的方式,因此不适用于我们的特定用例。我们只需要忍受两个文件中的重复项即可。

无论如何,您需要创建以下文件:

  • docker-compose.yml

它应该开始于……

version: '2'
services:
   ... our services will go here

…我们可以开始在其中添加服务。

PHP-FPM

这用于在应用程序内处理代码的执行。我们还将使用它执行任意php脚本-例如运行Laravel附带的 artisan CLI 工具。 (请记住,这部分配置位于上方的「 service 」键下- 莫慌,后面会有完整的代码片段)

app:
  build:
    context: ./
    dockerfile: app.dockerfile
  working_dir: /var/www
  volumes:
    - ./:/var/www
  environment:
    - "DB_PORT=3306"
    - "DB_HOST=database"
view rawdocker-compose.yml hosted with ❤ by GitHub

注意:

  • 我们将使用单独的 app.dockerfile *(line ** 4 )* 来构建我们的镜像,因为我们想精确地控制PHP使用的扩展模块。
  • 我们将工作目录设置为 /var/www,这是应用代码位于容器内的位置,因此,如果我们将 CD 附加到容器上,则可以避免将 CD 放入该文件夹中。它还将使 exec 命令更短(我们将很快看到一个示例)
  • 我们使用单个的数据卷定义 ./:/var/www 将主机当前目录中的所有内容挂载到容器中的 /var/www 目录中。这将使我们能够对源代码进行更改,并将其立即体现在正在运行的应用程序中。这会使您的应用在浏览器中有延迟-滞后几百毫秒(尤其是在 OSX 上),但不要担心-在第2部分中,当我们过渡到生产设置时,速度问题将不再存在。

host:容器卷映射说明

  • 在此处设置环境变量 DB_PORTDB_HOST 以匹配我们稍后创建的数据库容器

现在我们需要创建我们在上面的 build 设置中引用的 app.dockerfile

FROM php:7.0.4-fpm

RUN apt-get update && apt-get install -y libmcrypt-dev \
    mysql-client libmagickwand-dev --no-install-recommends \
    && pecl install imagick \
    && docker-php-ext-enable imagick \
    && docker-php-ext-install mcrypt pdo_mysql

注意:

  • 在这里使用 php:7.0.4-fpm,你可以选择任何 PHP 版本。
  • 剩下的就是典型的 Laravel CRUD 应用程序所需要的基本依赖,并且额外添加了 imagick 依赖(我有一些应用需要图片处理 :))

    NGINX

接下来,我们需要配置一个 Web 服务器,用来处理静态文件以及将请求传递给 Laravel 应用程序处理。我们将遵循与以前相同的模式,这次将服务命名为 web及其附带文件web.dockerfile

web:
  build:
    context: ./
    dockerfile: web.dockerfile
  working_dir: /var/www
  volumes_from:
    - app
  ports:
    - 8080:80

注意:

  • 我们在这里使用 volumes_from 复用我们在上面的PHP-FPM服务中定义的内容。这意味着该 nginx 容器将继承 /var/www目录(该目录又挂载到我们的开发机上)
  • 我们将主机上的端口 8080 映射到容器中的 80 。这样一来,我们就可以访问正在开发中的 0.0.0.0:8080,而无需弄混主机名了。
    接下来,我们将创建上述的 web.dockerfile :
FROM nginx:1.10

ADD vhost.conf /etc/nginx/conf.d/default.conf

注意:

  • 如您所见,这只是标准的Nginx官方映像,并添加了我们本地目录中的 vhost.conf 文件(接下来创建)来配置服务器。

这是 vhost.conf 文件

server {
    listen 80;
    index index.php index.html;
    root /var/www/public;

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

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

注意:

  • 请注意*** 12 *上我们是如何将php请求移交给 app:9000-这是可行的,因为 docker-compose 会自动链接我们的服务,使它们能够通过这些简单的主机名彼此 talk (通信)。
  • 剩下的只是非常基本的 nginx 配置-并未针对性能或安全性进行任何调整-我们将在另一篇文章中处理!

MYSQL

接下来,我们将配置数据库,但是我们需要处理该数据库的方式与以前的服务略有不同。借助 PHP-FPM 和 Nginx,我们希望可以从容器内部访问 主机 目录中的文件,以帮助加快开发过程。但这不适用于数据库-相反,我们希望容器中创建的文件能够持久保存,从而使我们能够停止和重新启动服务而不会丢失数据。可以通过卷来实现,只是这一次不需要将其与我们的主机文件同步。

version: '2'
services:

  database:
    image: mysql:5.6
    volumes:
      - dbdata:/var/lib/mysql
    environment:
      - "MYSQL_DATABASE=homestead"
      - "MYSQL_USER=homestead"
      - "MYSQL_PASSWORD=secret"
      - "MYSQL_ROOT_PASSWORD=secret"
    ports:
        - "33061:3306"

volumes:
  dbdata:

注意:

  • 16 行我们创建一个名为 dbdata 的卷(后面的:是必须的,yaml的限制,你不必在意)

  • 然后,在 7 行上,我们使用 <name>:<dir> 格式引用该卷,这就是「说从名为 dbdata 的卷中挂载目录/var/lib/mysql

  • 我们在第9、10、11和12行设置了 MySql docker 镜像所需的环境变量。

  • 我们使用 homestead 作为数据库/用户名,并使用 secret 作为密码,因为这些值与Laravel自带的 .env 配置文件中的默认值相匹配,这意味着我们不用再修改 .env 文件了。

  • 最后,在第13行,我们在主机上创建一个 33061 的端口映射到容器内的常规端口 3306。这样做仅仅是为了在开发过程中允许外部工具更容易地访问数据库-在生产设置中将不需要它。

所有服务

现在让我们看一下最终的 docker-compose.yml,以了解这些组件是如何组合在一起的。

version: '2'
services:

  # The Application
  app:
    build:
      context: ./
      dockerfile: app.dockerfile
    working_dir: /var/www
    volumes:
      - ./:/var/www
    environment:
      - "DB_PORT=3306"
      - "DB_HOST=database"

  # The Web Server
  web:
    build:
      context: ./
      dockerfile: web.dockerfile
    working_dir: /var/www
    volumes_from:
      - app
    ports:
      - 8080:80

  # The Database
  database:
    image: mysql:5.6
    volumes:
      - dbdata:/var/lib/mysql
    environment:
      - "MYSQL_DATABASE=homestead"
      - "MYSQL_USER=homestead"
      - "MYSQL_PASSWORD=secret"
      - "MYSQL_ROOT_PASSWORD=secret"
    ports:
        - "33061:3306"

volumes:
  dbdata:

启动服务

如果您一直跟着做,我们就快成功了!但是,在启动环境之前,我们需要确保1)您按照帖子中前面的说明运行了composer install&2 )在项目的根目录中创建了以下文件(以上均已详细介绍)。

- docker-compose.yml
- app.dockerfile
- web.dockerfile
- vhost.conf

这里的 gist 包含了所有的文件,为你引用、复制、粘贴所需

一旦所有这些都准备就绪,就可以继续执行以下命令,这将启动所有3个服务。

docker-compose up

注意:

  • 首次运行此程序时,它需要几分钟的时间才能开始,因为它将需要下载所有3个服务的镜像。随后的开始时间将在1到2秒钟左右,所以不要被最初的下载时间所推迟。(译者注: 注意使用国内的镜像源或者提前下载好镜像 并docker load -i XXX 导入 ,避免因为网络问题卡在这里)

    最后的步骤,准备 Laravel 应用程序。

接下来的还有几个操作需要处理,如果你的 Laravel 应用是使用的是官方安装程序创建的,这些操作已经自动处理了。

环境配置文件

我们首先需要将.env.example 文件复制到我们自己的 .env 文件中。该文件不会被纳入版本控制,我们将为开发和生产提供单独的文件。现在,只需复制 .env.example-> .env

应用程序密钥和优化

接下来,我们需要设置应用程序密钥并运行优化命令。这两个都是由artisan处理的,但是因为 PHP 和整个 Laravel 应用运行在容器内部,所以我们不能像您平时操作一样,只是在本地计算机上运行php artisan key:generate-我们需要将这些命令发布到容器中。
幸运的是,docker-compose有一个非常好的抽象来处理此问题,所需的两个命令如下所示:

docker-compose exec app php artisan key:generate
docker-compose exec app php artisan optimize

直白的说,第一行的意思是:

在服务「app」使用的容器内执行命令php artisan key:generate

为了清晰起见,以下图片展示了这些命令是如何分解的:

每当您想使用artisan时,都将需要此模式-记住使用docker的全部目的是避免在本地计算机上安装 PHP 版本的麻烦,这就是我们的解决方法-通过将命令发送到容器中,而不是直接运行它们。

您将在 Laravel 项目中经常运行的其他一些命令:

docker-compose exec app php artisan migration --seed
docker-compose exec app php artisan make:controller MyController

我想您现在明白了。

小建议: 创建一个 alias 比如 phpd 这样不需要输入完整的命令, 例如: phpd artisan migrate --seed

一旦您执行了前面提到的两个命令 (artisan key:generate & artisan optimize) 程序现在将准备使用 — 继续并点击http://0.0.0.0:8080 在你的浏览器中,你会看到这个可爱的屏幕。

妈妈,快看我的机器上没有安装PHP。

快乐开发吧!


下一步, 修改设置为 production.

现在已经有一些博客发布了关于Laravel像这样的开发环境, 但迄今为止我还没有发现一个如何完成以下重要步骤 — 使用此环境并使其准备好投入生产环境使用。我期待很快能和大家分享。

资源:

像这样吗?如果你这样做了,你会发现自己在做任何前端工作,也许你会喜欢我的一些课程https://egghead.io/instructors/shane-osbourne—很多都是免费的,包括Vanilla JS、Typescript、RxJS等。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.com/@shakyShane/laravel-d...

译文地址:https://learnku.com/laravel/t/38564

本帖已被设为精华帖!
本文为协同翻译文章,如您发现瑕疵请点击「改进」按钮提交优化建议
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 6

建议在内容页面添加一栏英文原文,类似于双语阅读的那种。

4年前 评论
wonbin

这篇博客是2017年发布的,有些年头了,而且软件的迭代更新很快,难免有些过时。在这里总结一下实践过程中遇到的一些坑

  • 注意在 daemon.json 中配置国内镜像地址,或者自己的镜像仓库

    [root@localhost docker-compose]# cat /etc/docker/daemon.json 
    {
    "registry-mirrors":["https://registry.docker-cn.com","https://kxv08zer.mirror.aliyuncs.com"],
    "exec-opts":["native.cgroupdriver=systemd"],
    "log-driver":"json-file",
    "log-opts":{
        "max-size":"100m"
    }
    }
  • docker run --rm -v $(pwd):/app composer/composer install
    镜像 composer/composer 已经弃用了, 改为 composer 了

  • 修改镜像的 yum 源, 参考docker apt-get 换源问题 , 强烈建议使用第二种 拷贝sources.list 文件的方式, 第一种有坑我没解决

  • php 依赖安装,这里我用的是 FROM php:7.2-fpm , 将 mysql-client 替换为 mariadb-client , mcrypt 7.1 的时候废弃了,7.2的时候移除了,所以在这 把 libmcrypt-dev 和 mcrypt 相关的都删掉, 或者简单起见直接去 hub.docker.io 上找个现成的dockerifle 替换掉, 仅供参考 dongshufeng/my-php
    或者 简单粗暴直接 用现成的 image

最后 跑起来了

Laravel

如果想使用 docker-compse 部署的项目,最好稍微系统的看一下这块,要不然你会发现好多坑,然后就弃坑了
好了就这么多 -:)

4年前 评论

好文章,讲的很清晰

4年前 评论

换了国内镜像,已然没法成功,安装了一晚上 :sob:

4年前 评论
Icy 4年前
bigbug-gg 4年前
cccyzloong 4年前
july1115 4年前
Bin

提个小建议,如果把代码的行好也加上,然后在说修改多少行的时候的,能找得更精准了。

4年前 评论

在本地安装docker for desktop, 然后用docker-composer安装,再也不担心污染本地环境了。想切换php 版本也太快了。

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!