Home Backend Development PHP Tutorial How to use Docker to deploy a PHP development environment

How to use Docker to deploy a PHP development environment

Jan 02, 2018 am 11:40 AM
docker php develop

本文主要介绍了如何使用Docker构建PHP的开发环境,文中作者也探讨了构建基于Docker的开发环境应该使用单容器还是多容器,各有什么利弊。推荐PHP开发者阅读。希望对大家有所帮助。

环境部署一直是一个很大的问题,无论是开发环境还是生产环境,但是 Docker 将开发环境和生产环境以轻量级方式打包,提供了一致的环境。极大的提升了开发部署一致性。当然,实际情况并没有这么简单,因为生产环境和开发环境的配置是完全不同的,比如日志等的问题都需要单独配置,但是至少比以前更加简单方便了,这里以 PHP 开发作为例子讲解 Docker 如何布置开发环境。

一般来说,一个 PHP 项目会需要以下工具:

  1. Web 服务器: Nginx/Tengine

  2. Web 程序: PHP-FPM

  3. 数据库: MySQL/PostgreSQL

  4. 缓存服务: Redis/Memcache

这是最简单的架构方式,在 Docker 发展早期,Docker 被大量的滥用,比如,一个镜像内启动多服务,日志收集依旧是按照 Syslog 或者别的老方式,镜像容量非常庞大,基础镜像就能达到 80M,这和 Docker 当初提出的思想完全南辕北辙了,而 Alpine Linux 发行版作为一个轻量级 Linux 环境,就非常适合作为 Docker 基础镜像,Docker 官方也推荐使用 Alpine 而不是 Debian 作为基础镜像,未来大量的现有官方镜像也将会迁移到 Alpine 上。本文所有镜像都将以 Alpine 作为基础镜像。

Nginx/Tengine

这部分笔者已经在另一篇文章 Docker 容器的 Nginx 实践中讲解了 Tengine 的 Docker 实践,并且给出了 Dockerfile,由于比较偏好 Tengine,而且官方已经给出了 Nginx 的 alpine 镜像,所以这里就用 Tengine。笔者已经将镜像上传到官方 DockerHub,可以通过

docker pull chasontang/tengine:2.1.2_f

获取镜像,具体请看 Dockerfile。

PHP-FPM

Docker 官方已经提供了 PHP 的 7.0.7-fpm-alpine 镜像,Dockerfile 如下:

FROM alpine:3.4

# persistent / runtime deps
ENV PHPIZE_DEPS \
    autoconf \
    file \
    g++ \
    gcc \
    libc-dev \
    make \
    pkgconf \
    re2c
RUN apk add --no-cache --virtual .persistent-deps \
    ca-certificates \
    curl

# ensure www-data user exists
RUN set -x \
  && addgroup -g 82 -S www-data \
  && adduser -u 82 -D -S -G www-data www-data
# 82 is the standard uid/gid for "www-data" in Alpine
# http://git.alpinelinux.org/cgit/aports/tree/main/apache2/apache2.pre-install?h=v3.3.2
# http://git.alpinelinux.org/cgit/aports/tree/main/lighttpd/lighttpd.pre-install?h=v3.3.2
# http://git.alpinelinux.org/cgit/aports/tree/main/nginx-initscripts/nginx-initscripts.pre-install?h=v3.3.2

ENV PHP_INI_DIR /usr/local/etc/php
RUN mkdir -p $PHP_INI_DIR/conf.d

##<autogenerated>##
ENV PHP_EXTRA_CONFIGURE_ARGS --enable-fpm --with-fpm-user=www-data --with-fpm-group=www-data
##</autogenerated>##

ENV GPG_KEYS 1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763

ENV PHP_VERSION 7.0.7
ENV PHP_FILENAME php-7.0.7.tar.xz
ENV PHP_SHA256 9cc64a7459242c79c10e79d74feaf5bae3541f604966ceb600c3d2e8f5fe4794

RUN set -xe \
  && apk add --no-cache --virtual .build-deps \
    $PHPIZE_DEPS \
    curl-dev \
    gnupg \
    libedit-dev \
    libxml2-dev \
    openssl-dev \
    sqlite-dev \
  && curl -fSL "http://php.net/get/$PHP_FILENAME/from/this/mirror" -o "$PHP_FILENAME" \
  && echo "$PHP_SHA256 *$PHP_FILENAME" | sha256sum -c - \
  && curl -fSL "http://php.net/get/$PHP_FILENAME.asc/from/this/mirror" -o "$PHP_FILENAME.asc" \
  && export GNUPGHOME="$(mktemp -d)" \
  && for key in $GPG_KEYS; do \
    gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \
  done \
  && gpg --batch --verify "$PHP_FILENAME.asc" "$PHP_FILENAME" \
  && rm -r "$GNUPGHOME" "$PHP_FILENAME.asc" \
  && mkdir -p /usr/src \
  && tar -Jxf "$PHP_FILENAME" -C /usr/src \
  && mv "/usr/src/php-$PHP_VERSION" /usr/src/php \
  && rm "$PHP_FILENAME" \
  && cd /usr/src/php \
  && ./configure \
    --with-config-file-path="$PHP_INI_DIR" \
    --with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
    $PHP_EXTRA_CONFIGURE_ARGS \
    --disable-cgi \
# --enable-mysqlnd is included here because it&#39;s harder to compile after the fact than extensions are (since it&#39;s a plugin for several extensions, not an extension in itself)
    --enable-mysqlnd \
# --enable-mbstring is included here because otherwise there&#39;s no way to get pecl to use it properly (see https://github.com/docker-library/php/issues/195)
    --enable-mbstring \
    --with-curl \
    --with-libedit \
    --with-openssl \
    --with-zlib \
  && make -j"$(getconf _NPROCESSORS_ONLN)" \
  && make install \
  && { find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all &#39;{}&#39; + || true; } \
  && make clean \
  && runDeps="$( \
    scanelf --needed --nobanner --recursive /usr/local \
      | awk &#39;{ gsub(/,/, "\nso:", $2); print "so:" $2 }&#39; \
      | sort -u \
      | xargs -r apk info --installed \
      | sort -u \
  )" \
  && apk add --no-cache --virtual .php-rundeps $runDeps \
  && apk del .build-deps

COPY docker-php-ext-* /usr/local/bin/

##<autogenerated>##
WORKDIR /var/www/html

RUN set -ex \
  && cd /usr/local/etc \
  && if [ -d php-fpm.d ]; then \
    # for some reason, upstream&#39;s php-fpm.conf.default has "include=NONE/etc/php-fpm.d/*.conf"
    sed &#39;s!=NONE/!=!g&#39; php-fpm.conf.default | tee php-fpm.conf > /dev/null; \
    cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
  else \
    # PHP 5.x don&#39;t use "include=" by default, so we&#39;ll create our own simple config that mimics PHP 7+ for consistency
    mkdir php-fpm.d; \
    cp php-fpm.conf.default php-fpm.d/www.conf; \
    { \
      echo &#39;[global]&#39;; \
      echo &#39;include=etc/php-fpm.d/*.conf&#39;; \
    } | tee php-fpm.conf; \
  fi \
  && { \
    echo &#39;[global]&#39;; \
    echo &#39;error_log = /proc/self/fd/2&#39;; \
    echo; \
    echo &#39;[www]&#39;; \
    echo &#39;; if we send this to /proc/self/fd/1, it never appears&#39;; \
    echo &#39;access.log = /proc/self/fd/2&#39;; \
    echo; \
    echo &#39;clear_env = no&#39;; \
    echo; \
    echo &#39;; Ensure worker stdout and stderr are sent to the main error log.&#39;; \
    echo &#39;catch_workers_output = yes&#39;; \
  } | tee php-fpm.d/docker.conf \
  && { \
    echo &#39;[global]&#39;; \
    echo &#39;daemonize = no&#39;; \
    echo; \
    echo &#39;[www]&#39;; \
    echo &#39;listen = [::]:9000&#39;; \
  } | tee php-fpm.d/zz-docker.conf

EXPOSE 9000
CMD ["php-fpm"]
##</autogenerated>##
Copy after login

首先,镜像继承自 alpine:3.4 镜像,使用 apk 命令安装 php 最小依赖,同时添加 www-data 作为 php-fpm 的运行用户,将 php 的配置文件指定到 /usr/local/etc/php,然后就是下载 php-src,编译安装,这里可以参考笔者之前写的 php 编译安装文章。参数都中规中矩。安装目录被指定到 /usr/local,然后使用 scanelf 获得所依赖的运行库列表,并且将其他安装包删除。将 docker-php-ext-configure、docker-php-ext-enable、docker-php-ext-install 复制到容器中,这三个文件用于后续安装扩展。然后将 php-fpm.conf 复制到配置目录,将 error_log 和 access_log 指定到终端标准输出,daemonize = no 表示不以服务进程运行。EXPOSE 9000 端口用于和其他容器通信,然后就是 CMD ["php-fpm"] 运行 php-fpm。而且工作目录被指定到 /var/www/html。

docker-compose

已经搞定了基础镜像,我们就可以使用基础镜像来配置容器,但是通过手工 docker 命令启动容器会非常麻烦。但是万幸的是官方已经提供了 docker-compose 命令来编排容器,只需要写一个 docker-compose.yaml 文件就行,具体可以参考官方文档。

version: &#39;2&#39;
services:
 php-fpm:
  image: php:7.0.7-fpm-alpine
  volumes:
   - "./src:/var/www/html"
  restart: always

 tengine:
  depends_on:
   - php-fpm
  links:
   - php-fpm
  image: chasontang/tengine:2.1.2_f
  volumes:
   - "./nginx.vh.default.conf:/etc/nginx/conf.d/default.conf"
  ports:
   - "80:80"
  restart: always
Copy after login

非常容易理解,这里定义了两个服务,php-fpm 依赖 php:7.0.7-fpm-alpine 镜像,并且将 src 文件夹映射为 /var/www/html 文件夹,tengine 服务依赖 php-fpm 服务,并且 link php-fpm 服务,这样就能通过网络与 php-fpm 容器通信,tengine 服务基于 chasontang/tengine:2.1.2_f 镜像,并将 nginx.vh.default.conf 文件映射为 /etc/nginx/conf.d/default.conf 文件。然后来看 nginx.vh.default.conf

server {
  listen    80;
  server_name localhost;

  #charset koi8-r;

  #access_log logs/host.access.log main;

  location / {
    root  html;
    index index.html index.htm;
  }

  #error_page 404       /404.html;

  # redirect server error pages to the static page /50x.html
  #
  error_page  500 502 503 504 /50x.html;
  location = /50x.html {
    root  html;
  }

  # proxy the PHP scripts to Apache listening on 127.0.0.1:80
  #
  #location ~ \.php$ {
  #  proxy_pass  http://127.0.0.1;
  #}

  location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    fastcgi_pass php-fpm:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    include fastcgi_params;
  }

  # deny access to .htaccess files, if Apache&#39;s document root
  # concurs with nginx&#39;s one
  #
  #location ~ /\.ht {
  #  deny all;
  #}
}
Copy after login

tengine 镜像实际上使用两个配置文件,一个是 /etc/nginx/nginx.conf,还有就是 /etc/nginx/conf.d/ 目录下的所有文件,因为 /etc/nginx/nginx.conf 中使用 include /etc/nginx/conf.d/*.conf; 包含了这个目录,也就是说,可以不需要去管 nginx 其他配置,只需要用自己的 nginx 虚拟主机配置替代默认的虚拟主机配置,或者说增加虚拟主机配置就行了。

从上面可以看到,default.conf 文件定义了一个 location 匹配包含 .php 的 URL,然后将其分割出 PATH_INFO 参数,将这些变量传递给 php-fpm:9000 的 php-fpm 服务。

It should be noted here that since Nginx and PHP-FPM are not on the same host, Nginx only does static file processing and routing forwarding, and the actual PHP file execution occurs in the PHP-FPM container. Therefore, the SCRIPT_FILENAME variable must use the directory in the PHP-FPM container, so it is specified by hard coding here. Of course, two containers can also share the same data volume, but the author believes that this is only to facilitate container orchestration and has no other benefits at all.

It’s easy! Now we can quickly start and update the environment.

Related recommendations:

The role of the open_basedir option in the PHP configuration file

apache + php configuration notes

IIS PHP configuration problem summary

The above is the detailed content of How to use Docker to deploy a PHP development environment. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

PHP and Python: Different Paradigms Explained PHP and Python: Different Paradigms Explained Apr 18, 2025 am 12:26 AM

PHP is mainly procedural programming, but also supports object-oriented programming (OOP); Python supports a variety of paradigms, including OOP, functional and procedural programming. PHP is suitable for web development, and Python is suitable for a variety of applications such as data analysis and machine learning.

How to exit the container by docker How to exit the container by docker Apr 15, 2025 pm 12:15 PM

Four ways to exit Docker container: Use Ctrl D in the container terminal Enter exit command in the container terminal Use docker stop &lt;container_name&gt; Command Use docker kill &lt;container_name&gt; command in the host terminal (force exit)

How to copy files in docker to outside How to copy files in docker to outside Apr 15, 2025 pm 12:12 PM

Methods for copying files to external hosts in Docker: Use the docker cp command: Execute docker cp [Options] &lt;Container Path&gt; &lt;Host Path&gt;. Using data volumes: Create a directory on the host, and use the -v parameter to mount the directory into the container when creating the container to achieve bidirectional file synchronization.

Why Use PHP? Advantages and Benefits Explained Why Use PHP? Advantages and Benefits Explained Apr 16, 2025 am 12:16 AM

The core benefits of PHP include ease of learning, strong web development support, rich libraries and frameworks, high performance and scalability, cross-platform compatibility, and cost-effectiveness. 1) Easy to learn and use, suitable for beginners; 2) Good integration with web servers and supports multiple databases; 3) Have powerful frameworks such as Laravel; 4) High performance can be achieved through optimization; 5) Support multiple operating systems; 6) Open source to reduce development costs.

Choosing Between PHP and Python: A Guide Choosing Between PHP and Python: A Guide Apr 18, 2025 am 12:24 AM

PHP is suitable for web development and rapid prototyping, and Python is suitable for data science and machine learning. 1.PHP is used for dynamic web development, with simple syntax and suitable for rapid development. 2. Python has concise syntax, is suitable for multiple fields, and has a strong library ecosystem.

How to check the name of the docker container How to check the name of the docker container Apr 15, 2025 pm 12:21 PM

You can query the Docker container name by following the steps: List all containers (docker ps). Filter the container list (using the grep command). Gets the container name (located in the "NAMES" column).

How to restart docker How to restart docker Apr 15, 2025 pm 12:06 PM

How to restart the Docker container: get the container ID (docker ps); stop the container (docker stop &lt;container_id&gt;); start the container (docker start &lt;container_id&gt;); verify that the restart is successful (docker ps). Other methods: Docker Compose (docker-compose restart) or Docker API (see Docker documentation).

How to start mysql by docker How to start mysql by docker Apr 15, 2025 pm 12:09 PM

The process of starting MySQL in Docker consists of the following steps: Pull the MySQL image to create and start the container, set the root user password, and map the port verification connection Create the database and the user grants all permissions to the database

See all articles