**本文年代久远,可能已经不适用。仅供参考!**新的php镜像参考maoxuner/php

多容器 apache+php+mariadb+redis

主要配置

构建php镜像

基于官方php镜像进行定制,增加所需的php扩展,修改php配置,以及创建虚拟主机。

Dockerfile

文件php/Dockerfile

FROM php:apache

# php configure
COPY php.ini /usr/local/etc/php/php.ini

# php extension
COPY sources.list /etc/apt/sources.list
RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libbz2-dev \
        libfreetype6-dev libjpeg62-turbo-dev libpng-dev \
    && rm -r /var/lib/apt/lists/* \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) zip bz2 gd mysqli pdo_mysql sockets \
    && pecl install redis \
    && docker-php-ext-enable redis

# php composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
    && php -r "if (hash_file('SHA384', 'composer-setup.php') === '544e09ee996cdf60ece3804abc52599c22b1f40f4323403c44d44fdfdd586475ca9813a858088ffbc1f233e9b180f061') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
    && php composer-setup.php --install-dir=/usr/local/bin --filename=composer \
    && php -r "unlink('composer-setup.php');"

# apache configure
RUN a2enmod rewrite.load

# apache vhosts
COPY vhosts/* /etc/apache2/sites-available/
RUN a2ensite demo.conf

说明

  • FROM php:apache未指定php版本号,默认使用最新的版本,当前7.2
  • docker-php-ext-install可以安装的组件如下,curl组件默认已经安装

    bcmath bz2 calendar ctype curl dba dom enchant exif fileinfo filter ftp gd gettext gmp hash iconv imap interbase intl json ldap mbstring mysqli oci8 odbc opcache pcntl pdo pdo_dblib pdo_firebird pdo_mysql pdo_oci pdo_odbc pdo_pgsql pdo_sqlite pgsql phar posix pspell readline recode reflection session shmop simplexml snmp soap sockets sodium spl standard sysvmsg sysvsem sysvshm tidy tokenizer wddx xml xmlreader xmlrpc xmlwriter xsl zend_test zip

  • 必要时需要安装一些依赖,并用docker-php-ext-configure配置编译参数
  • pecl可以安装pecl支持的组件,如redis

遇到的问题

直到我看到这个Installation of curl fails - easy.h should be in /include/curl/ #467,才发现curl组件默认已经安装。不过,又发现了编译curl组件的另连环坑:

Installation of curl fails - easy.h should be in /include/curl/

缺少依赖,而且依赖的路径不正确,解决方法

apt-get install -y libcurl4-openssl-dev
debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"
if [ ! -d /usr/include/curl ]; then
    ln -sT "/usr/include/$debMultiarch/curl" /usr/local/include/curl
fi

docker-compose

mariadbredis基本不需要定制,可以直接使用官方的镜像。我这里稍微做了一点定制。

docker-compose.yml

文件docker-compose.yml

version: '2'
services:
  mariadb:
    build: ./mariadb
    container_name: wx-mariadb
    hostname: wx-mariadb
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: cm9vdA==
    ports:
      - 3306:3306
    volumes:
      - db:/var/lib/mysql
  redis:
    build: ./redis
    container_name: wx-redis
    hostname: wx-redis
    restart: always
    ports:
      - 6379:6379
  php:
    build: ./php
    container_name: wx-php
    hostname: wx-php
    restart: always
    ports:
      - 80:80
    volumes:
      - ./html:/var/www/html
    depends_on:
      - mariadb
      - redis
volumes:
  db:

说明

  • ports暴露端口 80:80前一个是宿主机端口,后一个是容器端口
  • volumes分区映射 ./html:/var/www/html前者是宿主机的路径,后者是容器内的路径(不存在时会自动创建),可以理解为挂载。前者不能包含软连接,因为软连接只能在容器内部连接,因而找不到宿主机内的文件 db:/var/lib/mysql前者是创建的分区文件,后者是容器内的路径,可以理解为虚拟磁盘 分区映射是在镜像构建以后的操作。因此在镜像构建过程中,无法使用docker-compose.yml中定义的volumes

容器间的连接

localhost和127.0.0.1

  • 容器内的localhost127.0.0.1永远是指当前容器
  • 同一个docker-compose.yml创建的容器在同一个网络下
  • 同一个网络下的容器可以直接通过容器的ip或者名称?连接,Connect containers(写文章时找文档可找了好久)

    You can connect an existing container to one or more networks. A container can connect to networks which use different network drivers. Once connected, the containers can communicate using another container’s IP address or name.

  • link/links参数不再推荐使用(自动在/etc/hosts里添加各主机的ip主机名的记录)
  • 宿主机通过暴露的端口连接容器,尽量用127.0.0.1

注意

  • 在宿主机内,用mysql的web客户端(如adminer.php)连接数据库时,主机地址填service中的主键名mariadb(容器名wx-mariadb不能用来连接,可能是我的理解有问题,详细参考文档)。不能填写localhost或者127.0.0.1。 同理,连接redis要用主机名redis进行连接。 进行连接时,发送请求的主机是wx-php
  • 利用宿主机内的mysql客户端连接服务器的话,主机地址填写127.0.0.1。使用localhost连接mysql时,会使用sock进行连接,因而出错。

    ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’ (2 “No such file or directory”)

开发调试

IP白名单

Web框架往往只能在本机上(localhost或者127.0.0.1)进行开发调试。根据上述说明,此时的“本机”是指容器本身。因此,需要在框架的设置中,将宿主机在docker网络中的ip设置到白名单里。

参考文章