【问题标题】:docker-compose tmpfs not workingdocker-compose tmpfs 不工作
【发布时间】:2017-06-13 15:55:51
【问题描述】:

我有一个 docker-compose 文件,我试图通过将它创建的容器的根卷设为只读来保护它。

docker-compose.yml的相关部分:

version: '2'
services:
  mysql:
    image: mariadb:10.1
    read_only: true
    tmpfs:
    - /var/run/mysqld:uid=999,gid=999
    - /tmp
    volumes:
    - mysql:/var/lib/mysql
    restart: always
volumes:
  mysql:

问题是,tmpfs 没有被创建。如果我使用docker-compose run --rm mysql /bin/bash 运行容器实例,尽管有tmpfs 条目,/var/run/mysqld 目录仍然是只读的,并且对touch /var/run/mysqld/foo 的任何尝试都会失败。因为这是 MySQL 放置它的套接字和 pid 文件的地方,所以这会导致整个事情失败。我不确定为什么 tmpfs 条目在这种情况下不起作用。

mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] mysqld (mysqld 10.1.21-MariaDB-1~jessie) starting as process 1 ...
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Using mutexes to ref count buffer pool pages
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: The InnoDB memory heap is disabled
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: GCC builtin __atomic_thread_fence() is used for memory barrier
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Compressed tables use zlib 1.2.8
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Using Linux native AIO
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Using SSE crc32 instructions
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Initializing buffer pool, size = 256.0M
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Completed initialization of buffer pool
mysql_1    | 2017-01-27 20:53:45 140515784030144 [Note] InnoDB: Highest supported file format is Barracuda.
mysql_1    | 2017-01-27 20:53:48 140515784030144 [Note] InnoDB: 128 rollback segment(s) are active.
mysql_1    | 2017-01-27 20:53:48 140515784030144 [Note] InnoDB: Waiting for purge to start
mysql_1    | 2017-01-27 20:53:48 140515784030144 [Note] InnoDB:  Percona XtraDB (http://www.percona.com) 5.6.34-79.1 started; log sequence number 239403989
mysql_1    | 2017-01-27 20:53:48 140515005662976 [Note] InnoDB: Dumping buffer pool(s) not yet started
mysql_1    | 2017-01-27 20:53:48 140515784030144 [Note] Plugin 'FEEDBACK' is disabled.
mysql_1    | 2017-01-27 20:53:49 140515784030144 [Note] Server socket created on IP: '::'.
mysql_1    | 2017-01-27 20:53:49 140515784030144 [ERROR] Can't start server : Bind on unix socket: Read-only file system
mysql_1    | 2017-01-27 20:53:49 140515784030144 [ERROR] Do you already have another mysqld server running on socket: /var/run/mysqld/mysqld.sock ?
mysql_1    | 2017-01-27 20:53:49 140515784030144 [ERROR] Aborting

我可以验证目录的权限是否正确(并且mysql用户的UID是999):

$ ls -la /var/run/mysqld 
total 8
drwxrwxrwx 2 mysql mysql 4096 Jan 17 22:14 .
drwxr-xr-x 4 root  root  4096 Jan 18 22:55 ..

但我还是不能:

$ touch /var/run/mysqld/foo
touch: cannot touch '/var/run/mysqld/foo': Read-only file system

即使我以 root 身份运行。

任何想法我做错了什么?

顺便说一句,/tmp 文件系统工作正常。

【问题讨论】:

  • 你在使用 docker swarm 吗? docs.docker.com/compose/compose-file/#tmpfs 说“注意:在使用(版本 3)Compose 文件以 swarm 模式部署堆栈时,此选项将被忽略。”
  • 不。直接使用 docker-compose。
  • 我也是。 (填充)

标签: docker-compose tmpfs


【解决方案1】:

一些图像,如alpine 目录/var/run 只是指向/run 的链接 您可以验证使用

$ docker run --rm -ti mariadb:10.1 ls -lh /var/run
lrwxrwxrwx 1 root root 4 Aug  7 13:02 /var/run -> /run

这意味着/var/run/mysqld实际上是/run/mysqld

你更新的 docker-compose.yml 是

version: '2'
services:
  mysql:
    image: mariadb:10.1
    read_only: true
    tmpfs:
    - /run/mysqld:uid=999,gid=999
    - /tmp
    volumes:
    - mysql:/var/lib/mysql
    restart: always
volumes:
  mysql:

在这种情况下,只需让您的 tmpfs 指向 /run

看起来 /var/run 目录在 docker 中很特殊。

不,只是因为它是一个链接

【讨论】:

  • 谢谢,:uid=999,gid=999 解决了我的不可写目录问题。
【解决方案2】:

这方面我一直在做一些测试,看起来/var/run目录在docker中很特殊。

这是一些示例配置和输出:

  ubuntu:
    image: ubuntu
    command: "bash -c 'mount'"
    tmpfs:
      - /var/run
      - /var/cache

运行docker-compose up ubuntu 显示已安装的内容。可以看到 /var/cache 已安装,但 /var/run 未安装。

...
ubuntu_1           | tmpfs on /var/cache type tmpfs (rw,nosuid,nodev,noexec,relatime)
...

如果您使用docker-compose run ubuntu bash,您可以看到它也安装在那里,但不是/var/run

原因是 /var/run 通常是指向 /run 的符号链接,因此您将 /var/run/mysql 创建为 tmpfs 不起作用。

如果您将其更改为/run/mysql,它将起作用,但/run 通常无论如何都会挂载为tmpfs,因此您不妨将/run 设置为tmpfs。像这样:

  ubuntu:
    image: ubuntu
    command: "bash -c 'mount'"
    tmpfs:
      - /run
      - /var/cache

注意:我想修改我的答案并使用volumes展示如何做到这一点:

services:
  ubuntu:
    image: ubuntu
    command: "bash -c 'mount'"
    volumes:
      - cache_vol:/var/cache
      - run_vol:/run

volumes:
  run_vol:
    driver_opts:
      type: tmpfs
      device: tmpfs
  cache_vol:
    driver_opts:
      type: tmpfs
      device: tmpfs

这还允许您在需要时共享 tmpfs 挂载。

【讨论】:

  • 根据文档 tmpfs 挂载不能在容器之间共享:docs.docker.com/engine/admin/volumes/tmpfs/…
  • 是的,tmpfs 不能挂载,但上面是使用 tmpfs 类型的卷。这不是 tmpfs 挂载,而是使用 tmpfs 设备的卷挂载。理论上可以像任何其他卷一样共享。
  • 最近 Docker 在这方面的行为是否发生了变化,因为我曾经能够 tmpfs 挂载 /var/run/,而这只是在今天在频繁更新的 CoreOS 机器上重新启动时停止工作。
  • Bardi 可能是因为 /var/run 是一个符号链接
  • @dalore Tmpfs 的生命周期通常与容器的生命周期为 1:1。如果多个容器使用 tmpfs 类型和设备共享一个卷,那么卷中数据的生命周期会变成什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2016-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-18
相关资源
最近更新 更多