之前曾发布了一篇文章 用 docker-compose 构建 lnmp 开发环境,文中的 php 容器是通过自己写的 Dockerfile 构建的,其中 redis、swoole 扩展使用 pecl 指令在线安装,但是由于网络不佳,有时候代码包会下载失败,又得重新构建,很浪费时间。

Docker Hub 是 Docker 官方提供的一项容器镜像托管服务,它允许我们上传自己的镜像文件,方便与其他人共享。我们注册一个 Docker Hub 账号,然后上传自己生成的 php 镜像文件,这样下次使用到 php 容器的时候,直接从自己的 Docker Hub 仓库拉取,就不需要每次重新编译那些繁杂的 php 扩展了。

在命令行下,输入 docker login 指令登录自己的 Docker Hub 账号:

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: yangrz
Password:
Login Succeeded

我们基于 php:7.3.16-fpm 官方镜像来构建自己的镜像,Dockerfile 文件内容如下:

FROM php:7.3.16-fpm

RUN set -eux; \
    echo "deb http://mirrors.aliyun.com/debian stable main contrib non-free" > /etc/apt/sources.list; \
    echo "deb http://mirrors.aliyun.com/debian stable-proposed-updates main contrib non-free" >> /etc/apt/sources.list; \
    echo "deb http://mirrors.aliyun.com/debian stable-updates main contrib non-free" >> /etc/apt/sources.list; \
    echo "deb-src http://mirrors.aliyun.com/debian stable main contrib non-free" >> /etc/apt/sources.list; \
    echo "deb-src http://mirrors.aliyun.com/debian stable-proposed-updates main contrib non-free" >> /etc/apt/sources.list; \
    echo "deb-src http://mirrors.aliyun.com/debian stable-updates main contrib non-free" >> /etc/apt/sources.list; \
    \
    apt-get update; \
    \
    apt-get install -y --no-install-recommends \
    libbz2-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libpng-dev \
    libxml2-dev \
    libtidy-dev \
    libxslt1-dev \
    libzip-dev \
    libldap2-dev \
    libc-client-dev \
    libkrb5-dev \
    libicu-dev; \
    \
    docker-php-ext-install -j$(nproc) bcmath calendar exif gettext sockets dba mysqli pcntl pdo_mysql shmop sysvmsg sysvsem sysvshm; \
    \
    docker-php-ext-install -j$(nproc) bz2; \
    \
    docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ && \
    docker-php-ext-install -j$(nproc) gd; \
    \
    docker-php-ext-install -j$(nproc) soap wddx xmlrpc tidy xsl; \
    \
    docker-php-ext-install -j$(nproc) zip; \
    \
    docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu && \
    docker-php-ext-install -j$(nproc) ldap; \
    \
    docker-php-ext-configure imap --with-kerberos --with-imap-ssl && \
    docker-php-ext-install -j$(nproc) imap; \
    \
    docker-php-ext-configure opcache --enable-opcache && \
    docker-php-ext-install -j$(nproc) opcache; \
    \
    printf "\n\n\n" | pecl install redis-5.2.1 && \
    docker-php-ext-enable redis; \
    \
    printf "yes\nyes\nyes\nyes\n" | pecl install swoole-4.4.17 && \
    docker-php-ext-enable swoole; \
    \
    curl -o /usr/local/bin/composer https://mirrors.aliyun.com/composer/composer.phar && \
    chmod +x /usr/local/bin/composer && \
    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/; \
    \
    rm -r /var/lib/apt/lists/* /tmp/pear/download/*;

切换到 Dockerfile 所在目录,执行 docker build 指令构建镜像:

$ docker build -t yangrz/php-fpm:7.3.16 --rm=true .

参数 -t 指定镜像名称,格式 {username}/{镜像名}:{tag},参数 --rm=true 表示构建完成后删除中间镜像,指令最后面有个点 .,代表当前工作目录。

看到指令最后输出以下两行说明镜像构建成功:

Successfully built 99bb9b5ba627
Successfully tagged yangrz/php-fpm:7.3.16

使用 docker images 指令查看已构建的镜像:

$ docker images
REPOSITORY        TAG          IMAGE ID         CREATED          SIZE
yangrz/php-fpm    7.3.16       99bb9b5ba627     6 hours ago      502MB
php               7.3.16-fpm   9f48be9166e3     2 weeks ago      398MB

可以看到,由于我们自己的镜像安装了更多的 php 扩展,所以比官方镜像大了 104MB。

给镜像取别名:

$ docker tag yangrz/php-fpm:7.3.16 yangrz/php-fpm:latest

再次查看镜像:

$ docker images
REPOSITORY        TAG          IMAGE ID         CREATED          SIZE
yangrz/php-fpm    7.3.16       99bb9b5ba627     6 hours ago      502MB
yangrz/php-fpm    latest       99bb9b5ba627     6 hours ago      502MB
php               7.3.16-fpm   9f48be9166e3     2 weeks ago      398MB

可以看到此时多了个 latest 的 TAG,但镜像 ID 是一样的。按惯例,人们通常把最新构建的镜像取个 latest 别名。

把镜像上传到 Docker Hub:

$ docker push yangrz/php-fpm:7.3.16
The push refers to repository [docker.io/yangrz/php-fpm]
e16f20f59340: Pushed
f839175c2e23: Pushed
6c07d2f7b260: Pushed
0599d5fd0613: Pushed
2ad713318f25: Pushed
400d89cf8b22: Pushed
5b2f03a289f9: Pushed
10a0da35e86e: Pushed
7570269352d1: Mounted from library/php
1f3fba667c37: Pushed
c3a984abe8a8: Mounted from library/redis
7.3.16: digest: sha256:c8c7b106106bdc1edadbb462a71e57455658c8be355286c1d66b6c63c5fab03b size: 2829

$ docker push yangrz/php-fpm:latest
The push refers to repository [docker.io/yangrz/php-fpm]
e16f20f59340: Layer already exists
f839175c2e23: Layer already exists
6c07d2f7b260: Layer already exists
0599d5fd0613: Layer already exists
2ad713318f25: Layer already exists
400d89cf8b22: Layer already exists
5b2f03a289f9: Layer already exists
5b9a6f6a6366: Layer already exists
10a0da35e86e: Layer already exists
7570269352d1: Layer already exists
1f3fba667c37: Layer already exists
c3a984abe8a8: Layer already exists
latest: digest: sha256:c8c7b106106bdc1edadbb462a71e57455658c8be355286c1d66b6c63c5fab03b size: 2829

至此,自定义镜像上传完毕,可在线访问 https://hub.docker.com/r/yangrz/php-fpm

后期,如果要基于自定义镜像创建容器,指令举例如下:

$ docker run -d --name myphp -p 9000:9000 yangrz/php-fpm:latest

之前的 docker-compose.yml 中 php 容器的构建配置项如下:

    php:
        build:
          context: ./conf/php
        container_name: web-php
        ...

现在可以把它改成:

    php:
        image: yangrz/php-fpm:latest
        container_name: web-php
        ...

完整的配置文件打包下载:/upfiles/files/20200416/dockerlnmp-v2.zip