Docker实战-镜像制作

环境

安装docker、gitlab runner及和gitlab.com的runner绑定就不再赘述了。
  • gitlab,我使用的是gitlab.com
  • Ubuntu 运行gitlab runner和docker容器

制作Dockerfile

Dockerfile 文件内容

  1. 此文件中的 RUNCOPY 默认用户是root
  2. USER nobody 是指定在之后操作命令是基于nobody用户
FROM alpine:latest

RUN apk --no-cache add \
    nginx \
    supervisor \
    curl \
    openssl \
    openssl-dev \
    php7 \
    php7-fpm \
    php7-redis \
    php7-pdo

WORKDIR /var/www/html
COPY . /var/www/html/
RUN cd /var/www/html/ && \
    mkdir -p /etc/supervisor/conf.d/ && \ 
    mv env_config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf && \
    chmod +x /etc/supervisor/conf.d/supervisord.conf && \
    mv env_config/nginx.conf /etc/nginx/nginx.conf && \
    mv env_config/fpm-pool.conf /etc/php7/php-fpm.d/www.conf && \
    mv env_config/php.ini /etc/php7/conf.d/zzz_custom.ini && \
    mv -f test_src/* /var/www/html/

USER nobody

EXPOSE 8080

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

.gitlab-ci.yml内容

stages:
- build

build:
    stage: build
    script:
        - sudo docker build -t ahcometrue/php-nginx-redis:latest .
    tags:
        - pack

因为存在多个项目,而运行环境只是配置的差别,所以就把ahcometrue/php-nginx-redis作为基础镜像,故出现了一下问题。

此镜像的权限信息:

// 进程信息
$ ps aux
PID   USER     TIME  COMMAND
1 nobody    0:00 {supervisord} /usr/bin/python2 /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
7 nobody    0:00 nginx: master process nginx -g daemon off;
8 nobody    0:00 {php-fpm7} php-fpm: master process (/etc/php7/php-fpm.conf)
9 nobody    0:00 nginx: worker process

//当前用户
$ whoami
nobody

//当前用户 用户ID 组ID
$ id
uid=65534(nobody) gid=65534(nobody)

//nginx配置文件权限
$ ls -al /etc/nginx/
...
-rw-r--r--    1 root     root          2295 Sep 20 03:32 nginx.conf
...

//PHP配置文件权限
$ ls -al /etc/php7/
...
-rw-r--r--    1 root     root          5329 Aug 30 00:13 php-fpm.conf
-rw-r--r--    1 root     root         71982 Aug 30 00:13 php.ini
...

$ ls -al /etc/php7/conf.d/
-rw-r--r--    1 root     root            27 Sep 20 03:32 zzz_custom.ini
  1. 再次覆盖nginx.confphp.ini等文件时权限问题
  2. 运行容器时 CMD 执行的权限问题

出现的问题

先看下Dockerfile文件内容:

第一版本

FROM ahcometrue/php-nginx-redis:latest

ENV BASE_DIR /var/www/html

COPY . $BASE_DIR

RUN cd $BASE_DIR && \
    cp -f $BASE_DIR/.docker/nginx/nginx.conf /etc/nginx/nginx.conf && \
    cp -f $BASE_DIR/.docker/php/fpm-pool.conf /etc/php7/php-fpm.d/www.conf && \
    cp -f $BASE_DIR/.docker/php/php.ini /etc/php7/conf.d/zzz_custom.ini && \
    cp -f $BASE_DIR/.docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
    

此时runner执行失败,没有权限改变nginx.confzzz_custom.ini等文件。
原因是基础镜像最后指定了nobody用户,而这些文件属于root用户才有权限变更,故基于此有了第二版。

第二版本

FROM ahcometrue/php-nginx-redis:latest

ENV BASE_DIR /var/www/html

COPY . $BASE_DIR

//以下操作使用root用户
USER root

RUN cd $BASE_DIR && \
    cp -f $BASE_DIR/.docker/nginx/nginx.conf /etc/nginx/nginx.conf && \
    cp -f $BASE_DIR/.docker/php/fpm-pool.conf /etc/php7/php-fpm.d/www.conf && \
    cp -f $BASE_DIR/.docker/php/php.ini /etc/php7/conf.d/zzz_custom.ini && \
    cp -f $BASE_DIR/.docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf && \

此时镜像正常打包完成,容器可以正常跑起来,然而问题又来了。

$ ps aux
PID   USER     TIME  COMMAND
1 root    0:00 {supervisord} /usr/bin/python2 /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
7 root    0:00 nginx: master process nginx -g daemon off;
8 nobody    0:00 {php-fpm7} php-fpm: master process (/etc/php7/php-fpm.conf)
9 root    0:00 nginx: worker process
  1. 由于 php-fpm7 在文件中指定的是 nobody运行,而nginxsupervisord、却以root运行(因为在dockerfile中最后切换的用户是root),此时导致有些日志没有权限写入.
  2. 站点文件/var/www/html权限也是root导致laravel框架下的cache\storage/无权限写入。

第三版本


FROM ahcometrue/php-nginx-redis:latest

ENV BASE_DIR /var/www/html

COPY --chown=nobody . $BASE_DIR

//以下操作使用root用户
USER root

RUN cd $BASE_DIR && \
    cp -f $BASE_DIR/.docker/nginx/nginx.conf /etc/nginx/nginx.conf && \
    cp -f $BASE_DIR/.docker/php/fpm-pool.conf /etc/php7/php-fpm.d/www.conf && \
    cp -f $BASE_DIR/.docker/php/php.ini /etc/php7/conf.d/zzz_custom.ini && \
    cp -f $BASE_DIR/.docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf && \
    rm -rf .docker index.php test.html

// 以下操作使用nobody用户
USER nobody

//设置nginx监听接口
EXPOSE 8080

//使用supervisor启动 nginx & php
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
  1. COPY --chown=nobody . $BASE_DIR 解决了站点文件的权限,可以正常写入laravel框架下的cache\storage/
  2. USER nobody 切换用户,解决了nginxsupervisord进程以nobody身份运行

此时镜像权限问题全部解决。

日志持久化权限

在容器启动时把日志指定到宿主机是遇到容器里的日志无法写入。这时需要把宿主机的目录权限改下。

docker run -d -p 8080:8080 -v /data/log/:/var/log/ --name laravel-api laravel-php-redis:v2.0

此时是把容器中的日志/var/log/产生的数据持久化到 /data/log/ 下,在容器内部已经知道了当前用户的ID,故可以这样解决权限问题

sudo chown -R 65534 /data/log

常用命令列表

  • 进入容器内退出后删除

sudo docker run -ti --rm laravel-php-redis sh

  • 进入容器,退出后不会删除

sudo docker run -ti laravel-php-redis

  • 删除所有在运行或不再运行的容器

docker stop $(docker ps -q) & docker rm $(docker ps -aq)

  • 启动容器指定端口并挂载宿主机文件
//指定宿主机的端口80映射到容器内的8080端口 并指定宿主机的/data/log/ 目录持久化容器内的 /var/log/ 文件
docker run -d  -p 80:8080 -v /data/log/:/var/log/ --name laravel-api laravel-php-redis:v2.0
  • 进入运行的容器

docker exec -it laravel-api sh

你可能感兴趣的:(docker,gitlab)