环境
安装docker、gitlab runner及和gitlab.com的runner绑定就不再赘述了。
- gitlab,我使用的是gitlab.com
- Ubuntu 运行gitlab runner和docker容器
制作Dockerfile
Dockerfile 文件内容
- 此文件中的
RUN
、COPY
默认用户是root
-
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
- 再次覆盖
nginx.conf
、php.ini
等文件时权限问题 - 运行容器时 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.conf
、zzz_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
- 由于
php-fpm7
在文件中指定的是nobody
运行,而nginx
、supervisord
、却以root
运行(因为在dockerfile中最后切换的用户是root
),此时导致有些日志没有权限写入. - 站点文件
/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"]
-
COPY --chown=nobody . $BASE_DIR
解决了站点文件的权限,可以正常写入laravel框架下的cache\
和storage/
-
USER nobody
切换用户,解决了nginx
、supervisord
进程以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