不同文件夹的Dockerfile RUN行为不同

问题描述

注意:仅当通过Ansible模块处理docker时,才会重现该问题。

通过Ansible构建Docker映像,然后创建并启动一个容器。

我正在以alex用户的身份运行Ansible任务,并且启用了become选项。

Dockerfile通过Ansible模板处理,这是一个经过调整的Dockerfile文件(为简化起见),存储在/home/alex/MysqL文件夹中:

ARG MysqL_version

FROM MysqL/MysqL-server:$MysqL_version

RUN mkdir -p /home/MysqL/logs  && \
    chown -R MysqL:MysqL /home/MysqL/logs && \
    mkdir -p /home/MysqL/lib && \
    chown -R MysqL:MysqL /home/MysqL/lib 

MysqL角色的可用认变量:

---
MysqL_conf_host_path: /home/{{ lookup('env','USER') }}/MysqL
MysqL_log_path_host: /var/log/MysqL
MysqL_log_path_container: /home/MysqL/logs
MysqL_data_path_host: /var/lib/MysqL
MysqL_data_path_container: /home/MysqL/lib
MysqL_version: 8.0.21
docker_MysqL_image_name: bm_my_sql
docker_MysqL_container_name: bm_my_sql

构建图像,创建容器并启动它的Ansible任务(以MysqL角色实现):

- name: "Build {{ docker_MysqL_image_name }}:{{ MysqL_version }} Docker image"
  docker_image:
    source: build
    build:
      path: "{{ MysqL_conf_host_path }}" 
      args:
        MysqL_version: "{{ MysqL_version }}"
    name: "{{ docker_MysqL_image_name }}:{{ MysqL_version }}" # contain lowercase letters,numbers or - and _.
    state: present

- name: "Create {{ docker_MysqL_container_name }} container"
  docker_container:
    name: "{{ docker_MysqL_container_name }}"
    image: "{{ docker_MysqL_image_name }}:{{ MysqL_version }}"
    env:
      MysqL_ROOT_PASSWORD: "{{ MysqL_root_pwd }}"
    volumes:
      - "{{ MysqL_log_path_host }}:{{ MysqL_log_path_container }}"
      - "{{ MysqL_data_path_host }}:{{ MysqL_data_path_container }}"
    state: present

- name: "Start {{ docker_MysqL_container_name }} container"
  docker_container:
    name: "{{ docker_MysqL_container_name }}"
    state: started

然后登录到容器,看看是否应用chown:

$ docker exec -it bm_my_sql bash
bash-4.2# ls -la /home/MysqL/lib/
total 8
drwxr-xr-x 2 root root 4096 Aug 24 16:39 .
drwxr-xr-x 1 root root 4096 Aug 24 16:39 ..
bash-4.2# ls -la /home/MysqL/logs/
total 8
drwxr-xr-x 2 root root 4096 Aug 24 16:39 .
drwxr-xr-x 1 root root 4096 Aug 24 16:39 ..

创建了文件夹,但是所有者仍然是root。

在与其他文件夹上的所有者更改播放之前。结果很奇怪。例如,在Dockerfile中创建了2个目录树,并为每个目录树调用了chown:

ARG MysqL_version

FROM MysqL/MysqL-server:$MysqL_version

RUN mkdir -p /home/a/b/c && \
    chown -R MysqL:MysqL /home/a/b/c

RUN mkdir -p /var/log/MysqL/a/b/c && \
    chown -R MysqL:MysqL /var/log/MysqL/a/b/c

更改了容器,仅文件夹和/home/a/b/c所有者的结果。

/var/log/MysqL/a/b/c不存在。 /var/log/MysqL/存在于原始的“父”图像中。

这可能是什么原因,以及如何用所有者强制创建/var/log/MysqL/a/b/c目录树?

这些文件夹的行为不一致。有时它不起作用,有时又起作用。

为Ansible社区创建了issue

解决方法

我只是想复制,一切看起来都很好。从您提供的Dockerfile示例构建映像之后,容器中的内容如下所示:

sh-4.2# ls -la /var/log/mysql/a/b/c
total 8
drwxr-xr-x 2 mysql mysql 4096 Aug 24 14:37 . <-- the current directory (/var/log/mysql/a/b/c) has the mysql owner and group(if there would have been children entities in this directory,their owner would have also been changed because of the -R option you used.
drwxr-xr-x 3 root  root  4096 Aug 24 14:37 .. <-- the parent directory (/var/log/mysql/a/b) is owned by root,hence the mkdir -p was executed as root

也许您还在同一路径中的Dockerfile中声明了VOLUME?如果在声明了卷之后有任何构建步骤更改了卷中的数据,则这些更改将被丢弃。


在有问题的更新2之后进行编辑:

一步一步站在我这一边:

Dockerfile:

FROM mysql/mysql-server:8.0.21

RUN mkdir -p /home/mysql/logs  && \
    chown -R mysql:mysql /home/mysql/logs && \
    mkdir -p /home/mysql/lib && \
    chown -R mysql:mysql /home/mysql/lib

构建命令:

docker image build -t so-weird-chown .

在容器中打开控制台并检查所有权:

docker run -it so-weird-chown sh
[Entrypoint] MySQL Docker Image 8.0.21-1.1.17


sh-4.2# ls -la /home/mysql/logs
total 8
drwxr-xr-x 2 mysql mysql 4096 Aug 24 16:35 .
drwxr-xr-x 4 root  root  4096 Aug 24 16:35 ..
sh-4.2# ls -la /home/mysql/lib
total 8
drwxr-xr-x 2 mysql mysql 4096 Aug 24 16:35 .
drwxr-xr-x 4 root  root  4096 Aug 24 16:35 ..