Docker 制作容器镜像实践: Nginx+Php 二合一

建议点击 查看原文 查看最新内容。

原文链接: https://typonotes.com/posts/2023/07/11/docker-image-all-in-one-policy/

Docker 制作容器镜像的时候, 一定不能 All In One 吗? All in One 指的是把所有依赖都制作到同一个镜像中, 比如 app, mysql, redis。

一般来说 不要, 尽量保证一个镜像一个 应用。 解耦合。 可以这么理解 容器重启相当于机器重启 , 也就是 容器内的服务全部重启。 因此做镜像的时候应该尽量保证服务功能的 单一性简单

如图所示, 上述有三个服务 App, Mysql 和 Redis

  1. 当 App 从 v1 升级到 v2 的时候, Mysql 和 Redis 并不受影响。
  2. App 还可以还可以 横向扩展, 部署多个副本。

但是并不是 绝对的。 一些时候也可以根据实际情况做一些调整。

如上图, 是一个 nginx 代理的 php 服务。

这种情况下,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# nginx-php-fpm-proxy
server {
    # https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
    location ~ [^/]\.php(/|$) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;

        if (!-f $document_root$fastcgi_script_name) {
                return 404;
            }

        # Mitigate https://httpoxy.org/ vulnerabilities
        fastcgi_param HTTP_PROXY "";
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;

        # include the fastcgi_param setting
        include fastcgi_params;

        # https://www.digitalocean.com/community/tutorials/understanding-and-implementing-fastcgi-proxying-in-nginx
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}
  1. nginx 在配置代理 fastcgi 的时, 配置文件中需要提供项目文件(php文件)路径。 而且 nginx 和 php-fpm 所使用的项目文件 必须是一致的。 如果将 nginx 和 php-fpm 分开的话, 就需要将 同一份 文件放到两个 镜像中。 在发布的时候, 需要将 nginx 和 php-fpm 镜像版本对应起来。 个人觉得, 这种情况在管理上代价还是挺高的。
  2. 另外 nginx 在镜像中承担的任务 单一, 仅为代理。 通过实际观察, nginx 的故障率几乎为零。

综上, 我认为 nginx 和 php-fpm 是一个 应用整体

  1. 最终选择将 nginx 和 php-fpm 合并到一起。 在一个镜像中, 启动两个服务。
  2. 由于服务异常的概率, 选择 nginx 在后台启动。 php-fpm 在前台启动。 对外提供 nginx:80 服务, 存活检测 php-fpm:3000 服务。

注意: nginx 故障概率几乎为零 并不是完全为零。 依旧存在风险点: nginx 死掉而 php-fpm 存活的情况。

附件: Nginx + Php Dockerfile

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
FROM composer/composer:1.10.26 as composer

FROM library/php:7.4.33-fpm-bullseye as env
COPY --from=composer /usr/bin/composer /usr/bin/composer
RUN curl -L https://github.com/tangx/envsubst2/releases/download/v0.1.10/envsubst2-linux-amd64 \
        -o /usr/bin/envsubst2 \
    && chmod +x /usr/bin/envsubst2

# RUN sed -i "s/deb.debian.org/mirrors.aliyun.com/" /etc/apt/sources.list \
#   && sed -i "s/security.debian.org/mirrors.aliyun.com/" /etc/apt/sources.list 

# install extensions: oniguruma & mbstring
RUN apt update \
    && apt install -y \
        # 安全补丁
        curl openssl binutils patch m4 perl re2c \
        # 工具
        bash \
        # 安装 nginx
        nginx \
        ## 删除默认配置
        && rm -rf /etc/nginx/sites-available  \
                /etc/nginx/sites-enabled  \
        ## 日志地址
        && ln -sf /dev/stdout /var/log/nginx/access.log \
        && ln -sf /dev/stderr /var/log/nginx/error.log \
    # 安装 mbstring 依赖
    && apt install -y libonig-dev \
        && docker-php-ext-install mbstring \
    # 清理缓存
    && rm -rf /var/lib/apt/lists/*

### 本地配置
FROM env as builder
WORKDIR /var/www/html/
COPY --chown=www-data:www-data . .

RUN composer install

COPY ./bin/docker-entrypoint.sh /usr/bin/docker-entrypoint.sh
RUN chmod +x /usr/bin/docker-entrypoint.sh
ENTRYPOINT [ "/usr/bin/docker-entrypoint.sh" ]