La génération de keys GPG échoue sur l'image Docker Alpine Linux

J'ai effectué le test suivant sur un docker alpine linux:

ole@MKI:~$ docker run --rm -it alpine /bin/ash / # apk add --update duplicity fetch http://dl-4.alpinelinux.org/alpine/v3.3/main/x86_64/APKINDEX.tar.gz fetch http://dl-4.alpinelinux.org/alpine/v3.3/community/x86_64/APKINDEX.tar.gz (1/28) Installing libbz2 (1.0.6-r4) (2/28) Installing expat (2.1.0-r2) ... (28/28) Installing duplicity (0.7.05-r0) Executing busybox-1.24.1-r7.sortinggger OK: 72 MiB in 39 packages / # gpg --list-keys gpg: directory '/root/.gnupg' created gpg: new configuration file '/root/.gnupg/dirmngr.conf' created gpg: new configuration file '/root/.gnupg/gpg.conf' created gpg: WARNING: options in '/root/.gnupg' are not yet active during this run gpg: keybox '/root/.gnupg/pubring.kbx' created gpg: /root/.gnupg/trustdb.gpg: trustdb created / # gpg --list-keys / # gpg --gen-key gpg (GnuPG) 2.1.10; Copyright (C) 2015 Free Software Foundation, Inc. This is free software: you are free to change and redissortingbute it. There is NO WARRANTY, to the extent permitted by law. Note: Use "gpg2 --full-gen-key" for a full featured key generation dialog. GnuPG needs to construct a user ID to identify your key. Real name: Testing Email address: testing@test You selected this USER-ID: "Testing <testing@test>" Change (N)ame, (E)mail, or (O)kay/(Q)uit? O We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy. gpg: agent_genkey failed: No such file or directory Key generation failed: No such file or directory / # ls /root/.gnupg/ S.gpg-agent dirmngr.conf gpg.conf private-keys-v1.d pubring.kbx trustdb.gpg / # 

Toute idée de pourquoi la génération de key échoue?

[Edit] Je pourrais toujours générer les keys en utilisant une image ubuntu et les monter dans un volume. C'est finalement ce que je fais de toute façon, mais je pensais que ce serait bien d'avoir ce travail avec l'image alpine, donc j'ai collé la strace ci-dessous comme suggéré:

  / # strace -f gpg --gen-key execve("/usr/bin/gpg", ["gpg", "--gen-key"], [/* 6 vars */]) = 0 arch_prctl(ARCH_SET_FS, 0x7f75271edda8) = 0 set_tid_address(0x7f75271edde0) = 17 open("/etc/ld-musl-x86_64.path", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/lib/libz.so.1", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 fstat(3, {st_mode=S_IFREG|0755, st_size=87976, ...}) = 0 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0!\0\0\0\0\0\0"..., 960) = 960 mmap(NULL, 2187264, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f7526d4f000 mmap(0x7f7526f63000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x14000) = 0x7f7526f63000 close(3) = 0 open("/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/local/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/lib/libgcrypt.so.20", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 fstat(3, {st_mode=S_IFREG|0755, st_size=856824, ...}) = 0 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\214\0\0\0\0\0\0"..., 960) = 960 mmap(NULL, 2957312, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f7526a7d000 mmap(0x7f7526d45000, 40960, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xc8000) = 0x7f7526d45000 mmap(0x7f7526d4e000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7526d4e000 close(3) = 0 open("/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/local/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/lib/libgpg-error.so.0", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 fstat(3, {st_mode=S_IFREG|0755, st_size=67520, ...}) = 0 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p'\0\0\0\0\0\0"..., 960) = 960 mmap(NULL, 2166784, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f752686c000 mmap(0x7f7526a7b000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xf000) = 0x7f7526a7b000 close(3) = 0 open("/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/local/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/lib/libassuan.so.0", O_RDONLY|O_CLOEXEC) = 3 fcntl(3, F_SETFD, FD_CLOEXEC) = 0 fstat(3, {st_mode=S_IFREG|0755, st_size=67616, ...}) = 0 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\2204\0\0\0\0\0\0"..., 960) = 960 mmap(NULL, 2166784, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x7f752665b000 mmap(0x7f752686a000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xf000) = 0x7f752686a000 close(3) = 0 mprotect(0x7f7526f63000, 4096, PROT_READ) = 0 mprotect(0x7f7526d45000, 4096, PROT_READ) = 0 mprotect(0x7f7526a7b000, 4096, PROT_READ) = 0 mprotect(0x7f752686a000, 4096, PROT_READ) = 0 mprotect(0x7f75271ec000, 4096, PROT_READ) = 0 mprotect(0x7f752749a000, 8192, PROT_READ) = 0 fstat(0, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0 fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0 fstat(2, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 24), ...}) = 0 access("/etc/gcrypt/fips_enabled", F_OK) = -1 ENOENT (No such file or directory) open("/proc/sys/crypto/fips_enabled", O_RDONLY) = -1 ENOENT (No such file or directory) open("/etc/gcrypt/hwf.deny", O_RDONLY) = -1 ENOENT (No such file or directory) prlimit64(0, RLIMIT_CORE, NULL, {rlim_cur=0, rlim_max=RLIM64_INFINITY}) = 0 rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0 rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0 prlimit64(0, RLIMIT_CORE, {rlim_cur=0, rlim_max=RLIM64_INFINITY}, NULL) = 0 futex(0x7f75271f011c, FUTEX_WAKE_PRIVATE, 2147483647) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 rt_sigaction(SIGINT, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 8) = 0 rt_sigaction(SIGINT, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0 rt_sigaction(SIGHUP, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGHUP, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0 rt_sigaction(SIGTERM, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGTERM, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0 rt_sigaction(SIGQUIT, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGQUIT, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0 rt_sigaction(SIGSEGV, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGSEGV, {0x7f752726a170, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0 rt_sigaction(SIGUSR1, {0x7f752726a0d4, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0 rt_sigaction(SIGPIPE, {SIG_IGN, [], SA_RESTORER, 0x7f7526fad1c2}, NULL, 8) = 0 mmap(NULL, 32768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7527492000 getuid() = 0 mlock(0x7f7527492000, 32768) = 0 access("/root/.gnupg/gpg.conf-2.1.10", R_OK) = -1 ENOENT (No such file or directory) access("/root/.gnupg/gpg.conf-2.1", R_OK) = -1 ENOENT (No such file or directory) access("/root/.gnupg/gpg.conf-2", R_OK) = -1 ENOENT (No such file or directory) access("/root/.gnupg/gpg.conf", R_OK) = -1 ENOENT (No such file or directory) access("/root/.gnupg/options", R_OK) = -1 ENOENT (No such file or directory) stat("~/.gnupg", 0x7fff3556cc38) = -1 ENOENT (No such file or directory) stat("/root/.gnupg/gpg.conf", 0x7fff3556cc38) = -1 ENOENT (No such file or directory) open("/root/.gnupg/gpg.conf", O_RDONLY) = -1 ENOENT (No such file or directory) writev(2, [{"", 0}, {"gpg (GnuPG) 2.1.10; Copyright (C"..., 69}], 2gpg (GnuPG) 2.1.10; Copyright (C) 2015 Free Software Foundation, Inc.) = 69 writev(2, [{"", 0}, {"\n", 1}], 2 ) = 1 writev(2, [{"", 0}, {"This is free software: you are f"..., 121}], 2This is free software: you are free to change and redissortingbute it. There is NO WARRANTY, to the extent permitted by law. ) = 121 writev(2, [{"", 0}, {"\n", 1}], 2 ) = 1 access("/root/.gnupg/random_seed", F_OK) = -1 ENOENT (No such file or directory) open("/root/.gnupg/pubring.gpg", O_RDONLY) = -1 ENOENT (No such file or directory) open("/root/.gnupg/pubring.kbx", O_RDONLY) = -1 ENOENT (No such file or directory) access("/root/.gnupg/pubring.kbx", F_OK) = -1 ENOENT (No such file or directory) access("/root/.gnupg", F_OK) = -1 ENOENT (No such file or directory) mkdir("/root/.gnupg", 0700) = 0 write(2, "gpg: directory '/root/.gnupg", 28gpg: directory '/root/.gnupg) = 28 write(2, "' created\n", 10' created ) = 10 open("/usr/share/gnupg/dirmngr-conf.skel", O_RDONLY) = 3 umask(077) = 022 open("/root/.gnupg/dirmngr.conf", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4 ioctl(4, TIOCGWINSZ, 0x7fff3556c908) = -1 ENOTTY (Not a tty) umask(022) = 077 readv(3, [{"", 0}, {"# dirmngr-conf.skel - Skeleton t"..., 1024}], 2) = 1024 readv(3, [{"", 0}, {"nd receive keys to and from a ke"..., 1024}], 2) = 1024 writev(4, [{"# dirmngr.conf - Options for Dir"..., 1024}, {"L", 1}], 2) = 1025 readv(3, [{"", 0}, {" and only one is a Tor hidden\n# "..., 1024}], 2) = 704 writev(4, [{"DAP\n# support).\n#\n# Example HKP "..., 1024}, {"c", 1}], 2) = 1025 readv(3, [{"", 0}, {" and only one is a Tor hidden\n# "..., 1024}], 2) = 0 writev(4, [{"ally running or not (on a per se"..., 593}, {NULL, 0}], 2) = 593 close(4) = 0 close(3) = 0 write(2, "gpg: new configuration file '/ro"..., 54gpg: new configuration file '/root/.gnupg/dirmngr.conf) = 54 write(2, "' created\n", 10' created ) = 10 open("/usr/share/gnupg/gpg-conf.skel", O_RDONLY) = 3 umask(077) = 022 open("/root/.gnupg/gpg.conf", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 4 ioctl(4, TIOCGWINSZ, 0x7fff3556c908) = -1 ENOTTY (Not a tty) umask(022) = 077 readv(3, [{"", 0}, {"# These first three lines are no"..., 1024}], 2) = 1024 readv(3, [{"", 0}, {"\n\n# Uncomment the following opti"..., 1024}], 2) = 1024 writev(4, [{"# Options for GnuPG\n# Copyright "..., 1024}, {"o", 1}], 2) = 1025 readv(3, [{"", 0}, {"nce you may want to use this opt"..., 1024}], 2) = 1024 writev(4, [{"re than 1 secret key in your key"..., 1024}, {" ", 1}], 2) = 1025 readv(3, [{"", 0}, {"\n# \"0x12345678\". Note there is "..., 1024}], 2) = 1024 writev(4, [{"subkey, ensure that the cross\n# "..., 1024}, {"o", 1}], 2) = 1025 readv(3, [{"", 0}, {"r.\n#\n# verbose = show more infor"..., 1024}], 2) = 1024 writev(4, [{" another group. Note also that\n"..., 1024}, {"t", 1}], 2) = 1025 readv(3, [{"", 0}, {"ys to the keyserver.\n\n#keyserver"..., 1024}], 2) = 1024 writev(4, [{"o increase the amount\n# "..., 1024}, {"I", 1}], 2) = 1025 readv(3, [{"", 0}, {"c OS X and Windows, the default "..., 1024}], 2) = 413 writev(4, [{"Ds in key listings and\n# when a "..., 1024}, {"t", 1}], 2) = 1025 readv(3, [{"", 0}, {"c OS X and Windows, the default "..., 1024}], 2) = 0 writev(4, [{"o-viewer \"qiv %i\"\n# photo-viewer"..., 307}, {NULL, 0}], 2) = 307 close(4) = 0 close(3) = 0 write(2, "gpg: new configuration file '/ro"..., 50gpg: new configuration file '/root/.gnupg/gpg.conf) = 50 write(2, "' created\n", 10' created ) = 10 write(2, "gpg: WARNING: options in '/root/"..., 38gpg: WARNING: options in '/root/.gnupg) = 38 write(2, "' are not yet active during this"..., 37' are not yet active during this run ) = 37 access("/root/.gnupg", F_OK) = 0 getpid() = 17 uname({sysname="Linux", nodename="60fbb80a7ebb", ...}) = 0 getpid() = 17 open("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", O_WRONLY|O_CREAT|O_EXCL, 0644) = 3 write(3, " 17\n", 11) = 11 write(3, "60fbb80a7ebb", 12) = 12 write(3, "\n", 1) = 1 close(3) = 0 stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0 link("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", "/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17x") = 0 stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0 unlink("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17x") = 0 link("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", "/root/.gnupg/pubring.kbx.lock") = 0 stat("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17", {st_mode=S_IFREG|0644, st_size=24, ...}) = 0 access("/root/.gnupg/pubring.kbx", F_OK) = -1 ENOENT (No such file or directory) umask(077) = 022 open("/root/.gnupg/pubring.kbx", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 brk(0) = 0x7f7528fc5000 brk(0x7f7528fc8000) = 0x7f7528fc8000 umask(022) = 077 close(3) = 0 open("/root/.gnupg/pubring.kbx", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 ioctl(3, TIOCGWINSZ, 0x7fff3556c968) = -1 ENOTTY (Not a tty) writev(3, [{"\0\0\0 \1\1\0\2KBXf\0\0\0\0W\30+\243W\30+\243\0\0\0\0\0\0\0\0", 32}, {NULL, 0}], 2) = 32 close(3) = 0 write(2, "gpg: keybox '/root/.gnupg/pubrin"..., 37gpg: keybox '/root/.gnupg/pubring.kbx) = 37 write(2, "' created\n", 10' created ) = 10 open("/root/.gnupg/pubring.kbx.lock", O_RDONLY) = 3 read(3, " 17\n60fbb80a7ebb\n", 24) = 24 close(3) = 0 getpid() = 17 unlink("/root/.gnupg/pubring.kbx.lock") = 0 unlink("/root/.gnupg/.#lk0x00007f7526f64f40.60fbb80a7ebb.17") = 0 access("/root/.gnupg/secring.gpg", F_OK) = -1 ENOENT (No such file or directory) open("/dev/tty", O_RDWR) = 3 ioctl(3, TIOCGWINSZ, {ws_row=43, ws_col=174, ws_xpixel=0, ws_ypixel=0}) = 0 writev(3, [{"Note: Use \"gpg2 --full-gen-key", 30}, {"\" for a full featured key genera"..., 45}], 2Note: Use "gpg2 --full-gen-key" for a full featured key generation dialog. ) = 75 writev(3, [{"", 0}, {"\nGnuPG needs to construct a user"..., 59}], 2 GnuPG needs to construct a user ID to identify your key. ) = 59 writev(3, [{"Real name: ", 11}, {NULL, 0}], 2Real name: ) = 11 read(3, 

Le problème semble être lié à pinentry et au tty. La même command fonctionne parfaitement avec Ubuntu. tty dans un conteneur Alpine Linux affiche /0 alors que tty dans un conteneur Ubuntu affiche /dev/console

En exportant d'abord un tty correct pour gpg ( export GPG_TTY=/dev/console ), la command fonctionne et affiche la boîte de dialog du mot de passe.