Dockerfile 运行 对不同文件夹的行为不同
Dockerfile RUN behaviors differently for different folders
注意:只有在通过 Ansible 模块处理 docker 时才会重现该问题。
Docker通过Ansible构建镜像,然后创建并启动Container
我是 运行 Ansible 任务,作为 alex
用户启用了 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 角色的 Ansible 默认变量:
---
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。
在我尝试更改其他文件夹的所有者之前。它显示出奇怪的结果。例如,在 Docker 文件中创建了 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 之后编辑:
一步一步站在我这边:
Docker 文件:
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 ..
注意:只有在通过 Ansible 模块处理 docker 时才会重现该问题。
Docker通过Ansible构建镜像,然后创建并启动Container
我是 运行 Ansible 任务,作为 alex
用户启用了 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 角色的 Ansible 默认变量:
---
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。
在我尝试更改其他文件夹的所有者之前。它显示出奇怪的结果。例如,在 Docker 文件中创建了 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 之后编辑:
一步一步站在我这边:
Docker 文件:
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 ..