2024-04-11 渥太华微生活
如何在 Ubuntu 22.04 上通过 Docker Compose 安装 Laravel 网络应用 (How To Install and Set Up Laravel with Docker Compose on Ubuntu 22.04)
简介
应用程序容器化 (containerize an application) 是指调整应用程序及其组件,以便能够在轻量级环境例如容器中运行它的过程。此类环境是隔离的且一次性的,可用于开发、测试应用程序并将其部署到生产环境。
在本文中,我们将使用 Docker Compose 容器化 Laravel 应用程序以进行开发。完成后,您将拥有一个Laravel 应用程序,在三个独立的服务容器上运行:
运行 PHP8.2-FPM 的应用服务 (app service);
运行 MySQL 8.0 的数据库服务 (db service);
一个 nginx 服务 (nginx service),在将 Laravel 应用程序提供给最终用户之前,使用应用服务 (app service) 解析 PHP 代码。
为了简化开发过程并促进应用程序调试,我们将使用共享卷 (shared volumes) 保持应用程序文件同步。我们还将了解如何使用 docker-compose exec 命令在应用程序容器上运行 Composer 和 Artisan。
前提条件
Ubuntu 22.04 本地计算机或网络服务器,需要有 sudo 权限的非 root 用户 。
在您的服务器上安装了 Docker。
在您的服务器上安装了 Docker Compose。
第一步:下载演示应用程序
1、创建整个应用的文件夹,并进入该目录。
mkdir laravel-docker-compose-demo cd laravel-docker-compose-demo
2、通过 Composer 的 create-project 命令创建一个新的 Laravel 项目。
composer create-project laravel/laravel src
3、导航到应用程序源代码目录。
cd src
第二步:设置应用程序的 .env 文件
Laravel 配置文件位于应用程序根目录内名为 config 的目录中。此外,.env 文件用于设置依赖于环境的配置,例如身份验证信息和部署之间可能有所不同的任何信息。
.env 文件中包含的值将优先于位于 config 目录的常规配置文件中设置的值。
使用 nano 或您选择的文本编辑器打开此文件:
nano .env
当前 .env 文件包含使用本地 MySQL 数据库的设置,其中 127.0.0.1 作为数据库主机。我们需要更新 DB_HOST 变量,以便它指向我们将在 Docker 环境中创建的数据库服务。在文中,我们将数据库服务称为 db。继续将列出的 DB_HOST 值替换为数据库服务名称:
APP_NAME=Laravel APP_ENV=dev APP_KEY= APP_DEBUG=true APP_URL=http://localhost:8000 LOG_CHANNEL=stack DB_CONNECTION=mysql DB_HOST=db DB_PORT=3306 DB_DATABASE=laravel DB_USERNAME=laravel_user DB_PASSWORD=password
如果您愿意,也可以随意更改数据库名称、用户名和密码。这些变量将在稍后的步骤中使用,我们将设置 docker-compose.yml 文件来配置我们的服务。
第三步:设置应用程序的 Dockerfile
虽然 MySQL 和 Nginx 服务都将基于从 Docker Hub 获取的默认镜像,但我们仍然需要为应用程序容器构建自定义镜像。我们将为此创建一个新的 Dockerfile。
我们的应用镜像将基于来自 Docker Hub 的 php:8.2-fpm 官方 PHP 镜像。在 PHP-FPM 环境之上,我们将安装一些额外的 PHP 模块和 Composer 依赖管理工具。
我们还将创建一个新的系统用户,这是在开发应用程序时执行 artisan 和 composer 命令所必需的。uid 设置可确保容器内的用户与运行 Docker 的主机上的系统用户具有相同的 uid。这样,由这些命令创建的任何文件都会以正确的权限复制到主机中。
使用以下命令创建新的 Dockerfile:
nano Dockerfile
将以下内容复制到您的 Dockerfile 中:
FROM php:8.2-fpm # Arguments defined in docker-compose.yml ARG user ARG uid # Install system dependencies RUN apt-get update && apt-get install -y \ git \ curl \ libpng-dev \ libonig-dev \ libxml2-dev \ zip \ unzip # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install PHP extensions RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd # Get latest Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer # Create system user to run Composer and Artisan Commands RUN useradd -G www-data,root -u $uid -d /home/$user $user RUN mkdir -p /home/$user/.composer && \ chown -R $user:$user /home/$user # Set working directory WORKDIR /var/www USER $user
我们的 Dockerfile 首先定义基础镜像:php:8.2-fpm。
安装系统包和 PHP 扩展后,我们通过将 Composer 可执行文件从最新的官方镜像复制到我们自己的应用程序映像来安装 Composer。
然后使用在 Dockerfile 开头声明的 user 和 uid 参数创建并设置一个新的系统用户,这些值将由 Docker Compose 在构建时注入。
最后,我们将默认工作目录设置为 /var/www 并更改为新创建的用户。这将确保您在应用程序容器上运行 Composer 和 Artisan 命令时以普通用户身份进行连接,并且位于正确的目录中。
第四步:配置 Nginx
使用 Docker Compose 创建开发环境时,通常需要与服务容器共享配置或初始化文件,以便设置或引导这些服务。
为了设置 Nginx,我们将共享一个 laraveldemo.conf 文件,该文件将配置应用程序的服务方式。
使用以下命令创建 docker-compose/nginx 文件夹:
mkdir -p docker-compose/nginx
在该目录中打开一个名为 laraveldemo.conf 的新文件:
nano docker-compose/nginx/laraveldemo.conf
将以下 Nginx 配置复制到该文件:
server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/public; location ~ \.php$ { try_files $uri =404; 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; } location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } }
该文件将配置 Nginx 监听端口 80,并使用 index.php 作为默认索引页面。它将文档根目录设置为 /var/www/public,然后配置 Nginx 使用端口 9000 上的应用程序服务来处理 *.php 文件。
第五步:使用 Docker Compose 创建多容器环境
Docker Compose 使您能够在 Docker 上运行多容器环境,它使用服务定义来构建具有多个可以共享网络和数据卷的容器的完全可定制的环境。
我们将创建一个名为 docker-compose.yml 的新文件。通常,此文件位于应用程序文件夹的根目录,它定义您的容器化环境,包括您将用于构建容器的基础映像以及您的服务如何交互。
我们将在 docker-compose.yml 文件中定义三个不同的服务:app、db 和 nginx。
该应用程序服务 (app service) 将基于我们之前创建的 Dockerfile 构建一个名为 travellist 的镜像。该服务定义的容器将运行 php-fpm 服务器来解析 PHP 代码并将结果发送回 nginx 服务,该服务将在单独的容器上运行。mysql 服务定义了一个运行 MySQL 8.0 服务器的容器。我们的服务将共享一个名为 travellist 的桥接网络。
应用程序文件将通过绑定挂载在应用程序和 nginx 服务上同步。绑定挂载在开发环境中非常有用,因为它们允许在主机和容器之间实现高性能的双向同步。
在应用程序文件夹的根目录下,创建一个新的 docker-compose.yml 文件:
nano docker-compose.yml
典型的 docker-compose.yml 文件以版本定义开头,后跟服务节点,在该节点下定义了所有服务。共享网络通常在该文件的底部定义。
首先,将此样板代码复制到您的 docker-compose.yml 文件中:
version: "3.7" services: networks: laraveldemo: driver: bridge
我们现在将编辑服务节点以包含应用程序、数据库和 nginx 服务。
1、应用程序服务 (app service)
应用服务将设置一个名为 travellist-app 的容器。它基于与 docker-compose.yml 文件位于同一路径的 Dockerfile 构建新的 Docker 镜像。
尽管用作应用程序的文档根目录位于 nginx 容器中,但我们也需要应用程序文件位于应用程序容器内的某个位置,因此我们能够使用 Laravel Artisan 工具执行命令行任务。
将以下服务定义复制到服务节点下的 docker-compose.yml 文件内:
app: build: args: user:sammy uid:1000 context: ./ dockerfile: Dockerfile image: laraveldemo container_name: laraveldemo-app restart: unless-stopped working_dir: /var/www/ volumes: -./:/var/www networks: -laraveldemo
这些设置执行以下操作:
build:此配置告诉 Docker Compose 使用指定的路径(上下文)和 Dockerfile 来为应用程序服务构建本地镜像。参数 user 和 uid 被注入到 Dockerfile 中,用以在构建时自定义用户创建命令。
image:将用于正在构建的镜像的名称。
container_name:设置此服务的容器名称。
restart:总是重新启动,除非服务停止。
working_dir (工作目录):将此服务的默认目录设置为 /var/www。
volumes:创建一个共享卷,它将当前目录中的内容同步到容器内的 /var/www 。
networks (网络):设置此服务以使用名为 Travellist 的网络。
2、数据库服务 (db service)
db 服务使用 Docker Hub 中预构建的 MySQL 8.0 映像。由于 Docker Compose 会自动加载与 docker-compose.yml 文件位于同一目录中的 .env 变量文件,因此我们可以从上一步中创建的 Laravel .env 文件中获取数据库配置。
将以下服务定义包含在您的服务节点中,位于应用程序服务之后:
db: image:mysql:8.0 container_name: laraveldemo-db restart: unless-stopped environment: MYSQL_DATABASE:${DB_DATABASE} MYSQL_ROOT_PASSWORD:${DB_PASSWORD} MYSQL_PASSWORD:${DB_PASSWORD} MYSQL_USER:${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: -./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - laraveldemo
这些设置执行以下操作:
image:定义该容器应使用的 Docker 镜像。在本例中,我们使用 Docker Hub 中的 MySQL 8.0 镜像。
container_name:设置此服务的容器名称:travellist-db。
restart (重新启动):始终重新启动此服务,除非明确停止它。
environment (环境):定义新容器中的环境变量。我们使用从 Laravel .env 文件获取的值来设置 MySQL 服务,该服务将根据提供的环境变量自动创建新的数据库和用户。
volumes (卷):创建一个卷来共享将用于初始化应用程序数据库的 .sql 数据库转储。MySQL 镜像将自动导入容器内 /docker-entrypoint-initdb.d 目录中的 .sql 文件。
networks (网络):设置此服务以使用名为 travellist 的网络。
3、nginx 服务 (nginx service)
nginx 服务使用在轻量级 Linux 发行版 Alpine 之上预构建的 Nginx 映像。它创建一个名为 travellist-nginx 的容器,并使用端口定义创建从主机系统上的端口 8000 到容器内的端口 80 的重定向。
在服务节点中的数据库服务之后包含以下服务定义:
nginx: image:nginx:1.17-alpine container_name: laraveldemo-nginx restart: unless-stopped ports: -8000:80 volumes: -./:/var/www -./docker-compose/nginx:/etc/nginx/conf.d networks: - laraveldemo
这些设置执行以下操作:
image:定义该容器应使用的 Docker 镜像。在本例中,我们使用 Alpine Nginx 1.17 镜像。
container_name:设置此服务的容器名称:travellist-nginx。
restart (重新启动):始终重新启动此服务,除非明确停止它。
ports:设置端口重定向,允许通过外部端口 8000 访问容器内端口 80 上运行的 Web 服务器。
volumes (卷):创建两个共享卷。第一个卷会将当前目录的内容同步到容器内的 /var/www 。这样,当您对应用程序文件进行本地更改时,它们将快速反映在容器内由 Nginx 提供服务的应用程序中。第二个卷将确保我们的 Nginx 配置文件(位于 docker-compose/nginx/travellist.conf)被复制到容器的 Nginx 配置文件夹中。
networks (网络):设置此服务以使用名为 Travellist 的网络。
4、完成 docker-compose.yml 文件
这就是我们完成的 docker-compose.yml 文件的样子:
version: "3.7" services: app: build: args: user: sammy uid: 1000 context: ./ dockerfile: Dockerfile image: laraveldemo container_name: laraveldemo-app restart: unless-stopped working_dir: /var/www/ volumes: - ./:/var/www networks: - laraveldemo db: image: mysql:8.0 container_name: laraveldemo-db restart: unless-stopped environment: MYSQL_DATABASE: ${DB_DATABASE} MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_PASSWORD: ${DB_PASSWORD} MYSQL_USER: ${DB_USERNAME} SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - ./docker-compose/mysql:/docker-entrypoint-initdb.d networks: - laraveldemo nginx: image: nginx:alpine container_name: laraveldemo-nginx restart: unless-stopped ports: - 8000:80 volumes: - ./:/var/www - ./docker-compose/nginx:/etc/nginx/conf.d/ networks: - laraveldemo networks: laraveldemo: driver: bridge
第六步:使用 Docker Compose 运行应用程序
我们将使用 docker-compose 命令来构建应用程序镜像,并运行我们在设置中指定的服务。
使用以下命令构建应用程序映像:
docker-compose build app
此命令可能需要几分钟才能完成。 您将看到与此类似的输出:
Output Building app Sending build context to Docker daemon 377.3kB Step 1/11 : FROM php:7.4-fpm ---> 8c08d993542f Step 2/11 : ARG user ---> e3ce3af04d87 Step 3/11 : ARG uid ---> 30cb921ef7df Step 4/11 : RUN apt-get update && apt-get install -y git curl libpng-dev libonig-dev libxml2-dev zip unzip . . . ---> b6dbc7a02e95 Step 5/11 : RUN apt-get clean && rm -rf /var/lib/apt/lists/* ---> 10ef9dde45ad . . . Step 6/11 : RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd . . . ---> 920e4f09ec75 Step 7/11 : COPY --from=composer:latest /usr/bin/composer /usr/bin/composer ---> dbbcd44e44af Step 8/11 : RUN useradd -G www-data,root -u $uid -d /home/$user $user ---> db98e899a69a Step 9/11 : RUN mkdir -p /home/$user/.composer && chown -R $user:$user /home/$user ---> 5119e26ebfea Step 10/11 : WORKDIR /var/www ---> 699c491611c0 Step 11/11 : USER $user ---> cf250fe8f1af Successfully built cf250fe8f1af Successfully tagged travellist:latest
构建完成后,您可以使用以下命令在后台模式下运行环境:
docker-compose up -d
Output Creating laraveldemo-db ... done Creating laraveldemo-app ... done Creating laraveldemo-nginx ... done
这将在后台运行您的容器。要显示有关活动服务状态的信息,请运行:
docker-compose ps
你会看到这样的输出:
OutputName Command State Ports ----------------------------------------------------------------------------------------------- laraveldemo-app docker-php-entrypoint php-fpm Up 9000/tcp laraveldemo-db docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp laraveldemo-nginx nginx -g daemon off; Up 0.0.0.0:8000->80/tcp,:::8000->80/tcp
您的环境现已启动并正在运行,但我们仍然需要执行几个命令来完成应用程序的设置。您可以使用 docker-compose exec 命令在服务容器中执行命令,例如 ls -l 来显示应用程序目录中文件的详细信息:
docker-compose exec app ls -l
Output total 256 -rw-r--r-- 1 sammy sammy 737 Apr 18 14:21 Dockerfile -rw-r--r-- 1 sammy sammy 101 Jan 7 2020 README.md drwxr-xr-x 6 sammy sammy 4096 Jan 7 2020 app -rwxr-xr-x 1 sammy sammy 1686 Jan 7 2020 artisan drwxr-xr-x 3 sammy sammy 4096 Jan 7 2020 bootstrap -rw-r--r-- 1 sammy sammy 1501 Jan 7 2020 composer.json -rw-r--r-- 1 sammy sammy 179071 Jan 7 2020 composer.lock drwxr-xr-x 2 sammy sammy 4096 Jan 7 2020 config drwxr-xr-x 5 sammy sammy 4096 Jan 7 2020 database drwxr-xr-x 4 sammy sammy 4096 Apr 18 14:22 docker-compose -rw-r--r-- 1 sammy sammy 1017 Apr 18 14:29 docker-compose.yml -rw-r--r-- 1 sammy sammy 1013 Jan 7 2020 package.json -rw-r--r-- 1 sammy sammy 1405 Jan 7 2020 phpunit.xml drwxr-xr-x 2 sammy sammy 4096 Jan 7 2020 public -rw-r--r-- 1 sammy sammy 273 Jan 7 2020 readme.md drwxr-xr-x 6 sammy sammy 4096 Jan 7 2020 resources drwxr-xr-x 2 sammy sammy 4096 Jan 7 2020 routes -rw-r--r-- 1 sammy sammy 563 Jan 7 2020 server.php drwxr-xr-x 5 sammy sammy 4096 Jan 7 2020 storage drwxr-xr-x 4 sammy sammy 4096 Jan 7 2020 tests -rw-r--r-- 1 sammy sammy 538 Jan 7 2020 webpack.mix.js
我们现在将运行 composer install 来安装应用程序依赖项:
docker-compose exec app rm -rf vendor composer.lock docker-compose exec app composer install
你会看到这样的输出:
Output No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information. . . . Lock file operations: 89 installs, 0 updates, 0 removals - Locking doctrine/inflector (2.0.4) - Locking doctrine/instantiator (1.4.1) - Locking doctrine/lexer (1.2.3) - Locking dragonmantank/cron-expression (v2.3.1) - Locking egulias/email-validator (2.1.25) - Locking facade/flare-client-php (1.9.1) - Locking facade/ignition (1.18.1) - Locking facade/ignition-contracts (1.0.2) - Locking fideloper/proxy (4.4.1) - Locking filp/whoops (2.14.5) . . . Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 89 installs, 0 updates, 0 removals - Downloading doctrine/inflector (2.0.4) - Downloading doctrine/lexer (1.2.3) - Downloading dragonmantank/cron-expression (v2.3.1) - Downloading symfony/polyfill-php80 (v1.25.0) - Downloading symfony/polyfill-php72 (v1.25.0) - Downloading symfony/polyfill-mbstring (v1.25.0) - Downloading symfony/var-dumper (v4.4.39) - Downloading symfony/deprecation-contracts (v2.5.1) . . . Generating optimized autoload files > Illuminate\Foundation\ComposerScripts::postAutoloadDump > @php artisan package:discover --ansi Discovered Package: facade/ignition Discovered Package: fideloper/proxy Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully.
在测试应用程序之前,我们需要做的最后一件事是使用 artisan - Laravel 命令行工具进行数据库迁移:
docker-compose exec app php artisan migrate
现在转到浏览器,并在端口 8000 上访问服务器的域名或 IP 地址:
http://server_domain_or_IP:8000
注意:如果您在本地计算机上运行此演示,请使用 http://localhost:8000 从浏览器访问该应用程序。
你会看到这样的页面:
您可以使用 logs 命令来检查您的服务生成的日志:
docker-compose logs nginx
Attaching to travellist-nginx. . . travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:49:16 +0000] "GET / HTTP/1.1" 200 627 "-" "curl/7.82.0" travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:51:27 +0000] "GET / HTTP/1.1" 200 627 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0" travellist-nginx | 172.24.9.1 - - [18/Apr/2022:14:51:27 +0000] "GET /favicon.ico HTTP/1.1" 200 0 "http://localhost:8000/" "Mozilla/5.0 (X11; Linux x86_64; rv:89.0) Gecko/20100101 Firefox/89.0"
如果您想暂停 Docker Compose 环境,同时保留其所有服务的状态,请运行:
docker-compose pause
Output Pausing travellist-db ... done Pausing travellist-nginx ... done Pausing travellist-app ... done
然后您可以通过以下方式恢复您的服务:
docker-compose unpause
Output Unpausing travellist-app ... done Unpausing travellist-nginx ... done Unpausing travellist-db ... done
要关闭 Docker Compose 环境并删除其所有容器、网络和卷,请运行:
docker-compose down
Output Stopping travellist-nginx ... done Stopping travellist-db ... done Stopping travellist-app ... done Removing travellist-nginx ... done Removing travellist-db ... done Removing travellist-app ... done Removing network travellist-laravel-demo_travellist
结论:
在本文中,我们通过 Docker Compose 在 YAML 文件中定义我们的基础设施,从而设置了一个包含三个容器的 Docker 环境。
从现在起,您可以在 Laravel 应用程序上工作,而无需安装和设置本地 Web 服务器来进行开发和测试。
此外,您将使用可轻松复制和分发的一次性环境,这在开发应用程序以及转向生产环境时很有帮助。
编者注:新闻取自各大新闻媒体,新闻内容并不代表本网立场!文字和图片来自网络,版权归原作者所有。如有侵权,请速联系小编,立即删除。
全部评论 (0) |
---|