• 解决 Docker PHP “Failed opening required ‘xxx.php'” 的问题

    这个问题是我最近迁移本网站时遇到的。

    本网站是 Docker + PHP-FPM + nginx,迁移后,Wordpress 的 .php 访问报错:Failed opening required /xxx/wp-config.php

    很明显就是容器里没有权限。那么为什么会没权限呢?

    很久没搞这个的部署,忘得差不多了。经过重温与找资料,大概是这样解决的,不一定是完美的方案:

    原因:

    • Docker 的 PHP 运行的时候,默认是用www-data用户(并且uid=33),属于www-data用户组(且gid=33)
    • 某些系统自带了该用户与用户组(例如我网站迁移前所在的机器),某些没有自带(例如现机器)

    解决:

    1. 检查宿主机的用户、用户组是否有www-data,且 33 号的 uid/gid 是否被占用:
      # cat /etc/group
      # cat /etc/passwd
    2. 发现用户组 gid=33 被名为“tape”的用户组占用了(我的机器如此),似乎没有什么机会用到这个用户组,所以我把它的 id 改成 34:
      # groupmod -g 34 tape
    3. 创建 gid=33 的www-data用户组:
      # groupadd -g 33 www-data
    4. 创建 uid=33 的www-data用户,不创建home目录(-M),设置默认shell(-s)为nologin:
      # useradd -M -u 33 -g www-data -s /usr/sbin/nologin www-data

      至于为什么要这样创建,是为了尽可能模拟自带的www-data用户,在自带的机器上,passwd文件是这样的:
      # cat /etc/passwd | grep www-data
      www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin

      而执行上述 useradd 后,passwd 是这样的,已经很像了:
      www-data:x:33:33::/home/www-data:/usr/sbin/nologin
    5. 最后,在宿主机,把缺少权限的整个目录所有权,赋予给www-data
      # chown -R www-data:www-data some_directory
  • Docker 部署 Nginx+MariaDB(MySQL)+PHP 记录,与对应 docker-compose 实现

    Docker 火了这么多年,我也要学习体验一下。就在阿里云的服务器上部署一个 Nginx+MariaDB+PHP 环境吧。

    安装

    不同系统的安装方法见官方文档,包括了 Linux 的几个发行版和 Windows、MacOS 的详细步骤。我在 Linux 系统上安装。装完记得运行systemctl enable docker把 docker 调成自动启动。

    Docker Hub

    Docker 的各种 images 会发布在 Docker Hub,要善用这个网站来搜索想要的资源。

    网络

    在创建 docker 容器(container)之前,先考虑一下网络的架构。我打算创建 3 个容器:nginx、mariadb、php,其中,需要暴露的端口只有 nginx 容器的 80 (443) 端口。根据这篇文档中的:

    User-defined bridge networks are best when you need multiple containers to communicate on the same Docker host.

    我应该选择 bridge 网络,bridge 的具体的使用见此文档。在宿主机上运行

    docker network create --driver bridge my_bridge

    创建一个名称为 my_bridge 的bridge。

    Nginx

    先把 Nginx image 拉下来:docker pull nginx,默认会拉 latest 这个 tag (tags 可以在 Docker Hub 先搜索 nginx 然后点进去找到)。

    接下来创建容器:

    docker run --name my_nginx --network my_bridge -p 80:80 -v /var/www/php_env:/usr/share/nginx/html -e TZ="Asia/Shanghai" -d --restart always nginx

    参数解释:(详情见文档

    --name my_nginx           容器命名为my_nginx
    --network my_bridge       连接到my_bridge网络
    -p 80:80                  把容器的80端口(后)暴露为宿主机的80端口(前)
    -v /var/www/php_env:/usr/share/nginx/html   把宿主机的目录(前)mount到容器的指定路径
    -e TZ="Asia/Shanghai"     设置环境变量
    -d                        在后台运行
    --restart always          自动启动、重启
    nginx                     image名称

    如无意外,浏览器可以访问http://服务器IP的网页了。

    阅读更多…