web-dev-qa-db-fra.com

docker-compose tmpfs ne fonctionne pas

J'ai un fichier docker-compose que j'essaye de sécuriser en rendant les volumes racine des conteneurs qu'il crée en lecture seule.

Parties pertinentes de 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:

Le problème est que le tmpfs n'est pas en cours de création. Si j'exécute une instance du conteneur à l'aide de docker-compose run --rm mysql /bin/bash, les /var/run/mysqld le répertoire est toujours en lecture seule malgré l'entrée tmpfs et toute tentative de touch /var/run/mysqld/foo échoue. Puisque c'est là que MySQL place son fichier socket et pid, cela provoque l'échec du tout. Je ne sais pas pourquoi l'entrée tmpfs ne fonctionne pas dans ce cas.

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

Je peux vérifier que les autorisations sur le répertoire sont correctes (et que l'UID de l'utilisateur mysql est 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 ..

Mais je ne peux toujours pas:

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

Même si je lance en tant que root.

Des idées sur ce que je fais mal?

En passant, le /tmp le système de fichiers fonctionne correctement.

14
koehn

J'ai fait quelques tests à cet égard, il semble que le répertoire /var/run Soit spécial dans docker.

Voici quelques exemples de configuration et de sortie:

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

L'exécution de docker-compose up ubuntu Montre ce qui est monté. Peut voir que /var/cache Est monté mais que /var/run Ne l'est pas.

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

Si vous utilisez docker-compose run ubuntu bash, Vous pouvez voir qu'il est également monté là mais pas /var/run.

La raison en est que /var/run Est normalement un lien symbolique vers /run Et donc que vous créez /var/run/mysql En tant que tmpfs ne fonctionne pas.

Cela fonctionnera si vous le changez en /run/mysql, Mais /run Est normalement monté comme tmpfs de toute façon, vous pourriez tout aussi bien faire de /run Un tmpfs. Ainsi:

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

Remarque: je voudrais modifier ma réponse et montrer comment procéder à l'aide de 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

Cela vous permet également de partager les montures tmpfs si nécessaire.

26
dalore

quelques images comme Alpine le répertoire /var/run n'est qu'un lien vers /run vous pouvez vérifier qu'en utilisant

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

ce qui signifie que /var/run/mysqld est en fait /run/mysqld

votre docker-compose.yml mis à jour est

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:

dans ce cas, faites simplement pointer votre tmpfs vers /run

il semble que le répertoire/var/run soit spécial dans docker.

non, c'est juste parce que c'est un lien

1
Muayyad Alsadi