1

我使用环境变量创建了自己的 dockerfile (ubuntu:xenial)。这个 dockerfile 使用 php7.0-fpm php7.0-xml php7.0-mbstring php-mysql

dockerfiles 包含:

ENV           MYSQL_HOST=192.168.0.2
ENV           MYSQL_DBNAME=dbname_xyz
ENV           MYSQL_USERNAME=username_xyz
ENV           MYSQL_PASSWORD=password_xyz

...

RUN echo "clear_env = no" >> /etc/php/7.0/fpm/pool.d/www.conf

在 server.php 中,我尝试使用这些变量,但它们显然不为人所知

$host       = $_SERVER["MYSQL_HOST"];
$dbname     = $_SERVER["MYSQL_DBNAME"];
$username   = $_SERVER["MYSQL_USERNAME"];
$password   = $_SERVER["MYSQL_PASSWORD"];

$pdo = new \PDO("mysql:host=$host;dbname=$dbname", $username, $password);

运行显示错误:

FastCGI sent in stderr: "PHP message: PHP Notice:  Undefined index: MYSQL_HOST in /var/webdav/server.php on line 4

执行:container-shell 显示正确的值

php -r "echo getenv('MYSQL_HOST');"
env | grep MYSQL

有什么建议我要改变吗?

在 AymDEV 的反馈之后
更新 20211215 在 piotrekr 的反馈之后更新 20211215

完整的泊坞窗文件:

FROM          ubuntu:xenial
MAINTAINER    me@whatever.us

# Changing WEBDAV_PASSWORD doesn't work
# MYSQL_x aren't known to server.php
ENV           WEBDAV_USERNAME=admin
ENV           WEBDAV_PASSWORD=admin
ENV           MYSQL_HOST=192.168.0.2
ENV           MYSQL_DBNAME=dbname_xyz
ENV           MYSQL_USERNAME=username_xyz
ENV           MYSQL_PASSWORD=password_xyz

# Defaults
WORKDIR       /var/webdav
VOLUME        /var/webdav/public
VOLUME        /var/webdav/data


# Install zip
RUN           apt-get update && \
              DEBIAN_FRONTEND=noninteractive apt-get install -y zip unzip php-zip

# Install nginx with php7 support
RUN           apt-get update && \
              DEBIAN_FRONTEND=noninteractive apt-get install -y nginx php7.0-fpm php7.0-xml php7.0-mbstring php-mysql && \
              rm -rf /var/lib/apt/lists/*

# Install SabreDAV
RUN           php -r "readfile('http://getcomposer.org/installer');" > composer-setup.php && \
              php composer-setup.php --install-dir=/usr/bin --filename=composer && \
              php -r "unlink('composer-setup.php');" && \
              composer require sabre/dav ~3.2.2 && \
              rm /usr/bin/composer

# Set up entrypoint
COPY          /scripts/install.sh /install.sh

# Configure nginx
COPY          /config/nginx/default /etc/nginx/sites-enabled/default
COPY          /config/nginx/fastcgi_params /etc/nginx/fastcgi_params

# forward request and error logs to docker log collector
RUN           ln -sf /dev/stdout /var/log/nginx/access.log && \
              ln -sf /dev/stderr /var/log/nginx/error.log

# copy server.php for client -- sabredav communication
COPY          /web/server.php /var/webdav/server.php


#make environment variables available to php
RUN echo "clear_env = no" >> /etc/php/7.0/fpm/pool.d/www.conf

#nginx will be process with PID=1
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
CMD           /install.sh && service php7.0-fpm start && nginx

完整的 server.php

<?php

date_default_timezone_set('Europe/Berlin');
$baseUri = '/';
$host       = $_ENV["MYSQL_HOST"];
$dbname     = $_ENV["MYSQL_DBNAME"];
$username   = $_ENV["MYSQL_USERNAME"];
$password   = $_ENV["MYSQL_PASSWORD"];

$pdo = new \PDO("mysql:host=$host;dbname=$dbname", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

require_once 'vendor/autoload.php';

$authBackend      = new \Sabre\DAV\Auth\Backend\PDO($pdo);
$principalBackend = new \Sabre\DAVACL\PrincipalBackend\PDO($pdo);
$carddavBackend   = new \Sabre\CardDAV\Backend\PDO($pdo);
$caldavBackend    = new \Sabre\CalDAV\Backend\PDO($pdo);

$nodes = [
    new \Sabre\CalDAV\Principal\Collection($principalBackend),
    new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend),
    new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend),
];

$server = new \Sabre\DAV\Server($nodes);
if (isset($baseUri)) $server->setBaseUri($baseUri);

$server->addPlugin(new \Sabre\DAV\Auth\Plugin($authBackend));
$server->addPlugin(new \Sabre\DAV\Browser\Plugin());
$server->addPlugin(new \Sabre\CalDAV\Plugin());
$server->addPlugin(new \Sabre\CardDAV\Plugin());
$server->addPlugin(new \Sabre\DAV\Sync\Plugin());

$server->exec();
4

1 回答 1

0

实际上 - 一切都按设计工作。您没有看到 ENV 变量的原因有很多,而且您使用的方法有点缺陷。

TLDR:使用 docker-compose 并将 FPM 进程拆分到一个单独的容器中,以 fpm 作为入口点。

为什么它不起作用

由于这种情况有点复杂 - 我将尝试逐步说明它不适合您的原因。希望这会有所帮助。

  1. 您的 PHP 脚本在 FPM 工作程序中执行。这些工作人员中的每一个都将特定数据(上下文)传递给 PHP。例如,您可以在 $_SERVER 变量中看到该上下文:

     Array
        (
        [LANGUAGE] =>
        [LC_TIME] =>
        [LC_CTYPE] =>
        [LC_MONETARY] =>
        [TERM] => xterm
        [LC_COLLATE] =>
        [PATH] => /sbin:/usr/sbin:/bin:/usr/bin
        [LC_ADDRESS] =>
        [LANG] =>
        [LC_TELEPHONE] =>
        [LC_MESSAGES] =>
        [LC_NAME] =>
        [LC_MEASUREMENT] =>
        [LC_IDENTIFICATION] =>
        [LC_ALL] =>
        [PWD] => /
        [LC_NUMERIC] =>
        [LC_PAPER] =>
        [USER] => www-data
        [HOME] => /var/www
        [HTTP_ACCEPT] => */*
        [HTTP_USER_AGENT] => curl/7.47.0
        [HTTP_HOST] => localhost
        [REDIRECT_STATUS] => 200
        [SERVER_NAME] => _
        [SERVER_PORT] => 80
        [SERVER_ADDR] => 127.0.0.1
        [REMOTE_PORT] => 35542
        [REMOTE_ADDR] => 127.0.0.1
        [SERVER_SOFTWARE] => nginx/1.10.3
        [GATEWAY_INTERFACE] => CGI/1.1
        [REQUEST_SCHEME] => http
        [SERVER_PROTOCOL] => HTTP/1.1
        [DOCUMENT_ROOT] => /var/www/html
        [DOCUMENT_URI] => /print.php
        [REQUEST_URI] => /print.php
        [SCRIPT_NAME] => /print.php
        [CONTENT_LENGTH] =>
        [CONTENT_TYPE] =>
        [REQUEST_METHOD] => GET
        [QUERY_STRING] =>
        [SCRIPT_FILENAME] => /var/www/html/print.php
        [PATH_INFO] =>
        [FCGI_ROLE] => RESPONDER
        [PHP_SELF] => /print.php
        [REQUEST_TIME_FLOAT] => 1639586759.7522
        [REQUEST_TIME] => 1639586759
        )
    

    如果您从 CLI 打印出相同的变量 - 结果将完全不同(我猜您已经观察到了):

    Array
    (
        [HOSTNAME] => 580747313ddc
        [TERM] => xterm
        [MYSQL_PASSWORD] => password_xyz
        [LS_COLORS] => rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
        [WEBDAV_USERNAME] => admin
        [MYSQL_DBNAME] => dbname_xyz
        [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
        [PWD] => /var/www/html
        [WEBDAV_PASSWORD] => admin
        [MYSQL_USERNAME] => username_xyz
        [SHLVL] => 1
        [HOME] => /root
        [MYSQL_HOST] => 192.168.0.2
        [_] => /usr/bin/php
        [OLDPWD] => /etc/nginx
        [PHP_SELF] => print.php
        [SCRIPT_NAME] => print.php
        [SCRIPT_FILENAME] => print.php
        [PATH_TRANSLATED] => print.php
        [DOCUMENT_ROOT] =>
        [REQUEST_TIME_FLOAT] => 1639586851.762
        [REQUEST_TIME] => 1639586851
        [argv] => Array
            (
                [0] => print.php
            )
    
        [argc] => 1
    )
    
  2. ENV 已正确传递到容器中,如果您在容器中执行进程 - ENV 可供它们使用。这在上面的第二个示例中可以看到。但是,如果您查看容器中运行的进程:

root@580747313ddc:/var/www/html# ps -aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   1872   420 ?        Ss   16:20   0:00 /bin/sh -c service php7.0-fpm start && nginx
root        37  0.0  0.4  45560  9208 ?        S    16:20   0:00 nginx: master process nginx
root        43  0.0  0.1   3628  2908 pts/0    Ss   16:21   0:01 bash
www-data  3154  0.0  0.1  45932  4032 ?        S    16:38   0:00 nginx: worker process
www-data  3155  0.0  0.1  45932  3232 ?        S    16:38   0:00 nginx: worker process
www-data  3156  0.0  0.1  45932  3232 ?        S    16:38   0:00 nginx: worker process
www-data  3157  0.0  0.1  45932  3232 ?        S    16:38   0:00 nginx: worker process
www-data  3158  0.0  0.1  45932  3232 ?        S    16:38   0:00 nginx: worker process
root      3217  0.0  0.5 121364 10324 ?        Ss   16:41   0:00 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf)
www-data  3218  0.0  0.4 121708  9920 ?        S    16:41   0:00 php-fpm: pool www
www-data  3219  0.0  0.4 121708  9512 ?        S    16:41   0:00 php-fpm: pool www
root      3233  0.0  0.1   5472  2380 pts/0    R+   16:51   0:00 ps -aux

您可以检查它们中的每一个的环境,查看 PID=1 的进程(容器的入口点):

root@580747313ddc:/var/www/html# cat /proc/1/environ
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binHOSTNAME=580747313ddcWEBDAV_USERNAME=adminWEBDAV_PASSWORD=adminMYSQL_HOST=192.168.0.2MYSQL_DBNAME=dbname_xyzMYSQL_USERNAME=username_xyzMYSQL_PASSWORD=password_xyzHOME=/root

环境具有您创建的 ENV。这里一切都好。但是如果你看一下 FPM 过程:

root@580747313ddc:/var/www/html# cat /proc/3217/environ
root@580747313ddc:/var/www/html#

它是空的!

这是因为您将 FPM 作为服务运行(如在 systemd 服务中),这意味着您必须在服务的配置文件中定义这些环境变量,在本例中为/lib/systemd/system/php7.0-fpm.service.

但是,它可以做到——这样做不是很干净。

你可以做些什么来修复它

您可以通过简单地使用 php-fpm 作为容器的入口点来解决上述问题。这样 - 它将可以访问 ENV。这已经由官方php-fpm图像完成,我们可以尝试使用它们。这是一个使用 docker-compose 的最小可行示例:

码头工人-compose.yml:

version: '3'
services:
  web:
    image: nginx
    container_name: web
    depends_on:
      - php
    links:
      - php
    volumes:
      - ./html:/var/www/html
      - ./conf:/etc/nginx/conf.d/
    ports:
      - "8080:80"
  php:
    image: php:7.4-fpm-alpine
    environment:
      - MYSQL_PASS=pass123
    volumes:
      - ./html:/var/www/html

现在,在同一个文件夹中创建 html/print.php:

<?php print_r($_SERVER);?>

和 conf/default.conf:

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    root /var/www/html;
    location ~ \.php$ {

        try_files $uri = 404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param REQUEST_URI $request_uri;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        include        fastcgi_params;
    }

}

有了这个 - 只需运行docker-compose up -d然后curl localhost:8080/print.php

这应该会MYSQL_PASS在您的$_SERVER数组中为您提供预期的 env 变量:

Array
(
    [HOSTNAME] => 84a4d1e174d3
    [PHP_INI_DIR] => /usr/local/etc/php
    [SHLVL] => 1
    [HOME] => /home/www-data
    [PHP_LDFLAGS] => -Wl,-O1 -pie
    [PHP_CFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
    [PHP_VERSION] => 7.4.26
    [GPG_KEYS] => 42670A7FE4D0441C8E4632349E4FDC074A4EF02D 5A52880781F755608BF815FC910DEB46F53EA312
    [PHP_CPPFLAGS] => -fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
    [PHP_ASC_URL] => https://www.php.net/distributions/php-7.4.26.tar.xz.asc
    [MYSQL_PASS] => pass123
    [PHP_URL] => https://www.php.net/distributions/php-7.4.26.tar.xz
    [PATH] => /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    [WEBDAV_USER] => test
    [PHPIZE_DEPS] => autoconf       dpkg-dev dpkg       file        g++         gcc         libc-dev        make        pkgconf         re2c
    [PWD] => /var/www/html
    [PHP_SHA256] => e305b3aafdc85fa73a81c53d3ce30578bc94d1633ec376add193a1e85e0f0ef8
    [USER] => www-data
    [HTTP_ACCEPT] => */*
    [HTTP_USER_AGENT] => curl/7.77.0
    [HTTP_HOST] => localhost:8080
    [PATH_INFO] =>
    [SCRIPT_FILENAME] => /var/www/html/print.php
    [REDIRECT_STATUS] => 200
    [SERVER_NAME] => localhost
    [SERVER_PORT] => 80
    [SERVER_ADDR] => 172.18.0.3
    [REMOTE_PORT] => 55288
    [REMOTE_ADDR] => 172.18.0.1
    [SERVER_SOFTWARE] => nginx/1.21.4
    [GATEWAY_INTERFACE] => CGI/1.1
    [REQUEST_SCHEME] => http
    [SERVER_PROTOCOL] => HTTP/1.1
    [DOCUMENT_ROOT] => /var/www/html
    [DOCUMENT_URI] => /print.php
    [REQUEST_URI] => /print.php
    [SCRIPT_NAME] => /print.php
    [CONTENT_LENGTH] =>
    [CONTENT_TYPE] =>
    [REQUEST_METHOD] => GET
    [QUERY_STRING] =>
    [FCGI_ROLE] => RESPONDER
    [PHP_SELF] => /print.php
    [REQUEST_TIME_FLOAT] => 1639591114.4143
    [REQUEST_TIME] => 1639591114
    [argv] => Array
        (
        )

    [argc] => 0
)
于 2021-12-15T18:00:37.917 回答