在使用Docker时,将Apache和Perl分别放置在不同的容器中运行

在业务中有时会接受 Movable Type 的开发项目,但在使用 Docker 环境进行开发时,我想通过将 Apache 和 Perl 分开来实现环境的轻量化。

这次我将介绍我为了实现轻量化而进行的各种调查和实践方法。

在这里,我们仅介绍了用于建立开发环境的方法。
由于安全考虑,有些方法并非最佳选择,请勿直接在商业环境中使用。
本文仅涉及Apache和Perl部分,不包括涵盖Movable Type所需的设置、数据库和PHP容器等内容。

文件

docker-compose的配置文件是yaml格式的。

将 Perl 和 Apache 在不同的容器中运行。
另外,httpd 将使用基于最轻量级的 Alpine Linux 的版本。

version: '3'

services:
  perl:
    build:
      context: ./docker/perl
    volumes:
      - type: bind
        source: ./example
        target: /usr/local/apache2/vhosts/localhost
  httpd:
    build:
      context: ./docker/httpd
    volumes:
      - type: bind
        source: ./docker/httpd/httpd-vhosts.conf
        target: /usr/local/apache2/conf/extra/httpd-vhosts.conf
      - type: bind
        source: ./example
        target: /usr/local/apache2/vhosts/localhost
    ports:
      - "80:80"

Perl 容器

我們將使用多階段的建造方法。

FROM perl:5.36.0-threaded-bullseye AS build

RUN apt update

COPY cpanfile cpanfile
RUN cpanm --notest --installdeps .

FROM perl:5.36.0-slim-threaded-bullseye AS deploy

RUN apt update \
    && apt install -y fcgiwrap spawn-fcgi

COPY --from=build /usr/local/lib/perl5 /usr/local/lib/perl5

ARG FCGI_PORT=9000
RUN sed -ie "s/^FCGI_SOCKET=.*$/FCGI_PORT=\"${FCGI_PORT}\"\nFCGI_ADDR=\"0.0.0.0\"/g" /etc/init.d/fcgiwrap
EXPOSE ${FCGI_PORT}

CMD ["bash", "-c", "service fcgiwrap start && tail -f /dev/null"]

在构建阶段,从 cpanfile 安装所需的模块。
在部署阶段,根据没有构建工具的轻量级 Perl 镜像,复制从构建阶段安装的模块,并进行将 Perl 设置为 CGI 以便运行的设置。

关于多阶段构建,我参考了这里的Gist。

我决定试着放一个模块进去看看。

requires 'HTML::Entities';

Apache 容器

<VirtualHost *:80>
    ServerName localhost
    DocumentRoot "/usr/local/apache2/vhosts/localhost/htdocs"

    Alias /cgi-bin/ "/usr/local/apache2/vhosts/localhost/cgi-bin/"

    <Directory "/usr/local/apache2/vhosts/localhost/htdocs">
        Options None
        AllowOverride None
        Require all granted

        DirectoryIndex index.html
    </Directory>

    <Directory "/usr/local/apache2/vhosts/localhost/cgi-bin">
        AllowOverride None
        Options None
        Require all granted

        <FilesMatch "\.cgi$">
            ProxyFCGIBackendType GENERIC
            SetHandler "proxy:fcgi://perl:9000"
        </FilesMatch>
    </Directory>
</VirtualHost>

如果文件名以 .cgi 结尾,则设置代理,并使用 Perl 容器中的 Perl。

FROM httpd:2.4.54-alpine3.17

RUN sed -i -Ee 's/#(LoadModule proxy_module modules\/mod_proxy.so)/\1/g' /usr/local/apache2/conf/httpd.conf \
    && sed -i -Ee 's/#(LoadModule proxy_fcgi_module modules\/mod_proxy_fcgi.so)/\1/g' /usr/local/apache2/conf/httpd.conf \
    && sed -i -Ee 's/#(Include conf\/extra\/httpd-vhosts.conf)/\1/g' /usr/local/apache2/conf/httpd.conf

启用代理设置。

样本文件.

将显示Perl版本的文件放置在example/cgi-bin/index.cgi中。

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';

print "Content-type: text/html\n\n";
print "Hello World!<br>";
print "Perl Version: $^V<br>";

如果您在WSL(Windows Subsystem for Linux)或其他Linux平台上放置文件,请授予执行权限。

chmod a+x example/cgi-bin/index.cgi

在example/htdocs/index.html中也放置一个样本文件。

Hello HTML!

确认行动

创建文件后,启动容器进行操作确认。

docker-compose up -d --build

http://localhost/index.html にアクセスして Hello HTML! と表示されることを確認します。

http://localhost/cgi-bin/index.cgi にアクセスして以下のように表示されることを確認します。

Hello World!
Perl Version: v5.36.0

确认操作后,将关闭容器。

docker-compose down --remove-orphans -v
bannerAds