Docker-alpine: GNU Screen seems to be broken

Created on 16 Apr 2016  路  16Comments  路  Source: gliderlabs/docker-alpine

I was trying to fix https://github.com/chamunks/alpine-rtorrent image when I bumped into the issue which is that GNU screen on Alpine Linux image is not usable in a TTY mode (daemon mode works, but there is a little point in that if you cannot really see the terminal).

Here is a minimal Dockerfile to reproduce the issue:

FROM alpine

RUN apk add --no-cache screen

Here is how I run it:

$ docker build -t alpine-screen-issue .
$ docker run -it --rm alpine-screen-issue sh
# screen

Here is the error I get:

Cannot access '/3': No such file or directory

(/3 varies from machine to machine, so it is some sort of a descriptor.)

Here is strace log:

access("/root/.nethackrc", F_OK)        = -1 ENOENT (No such file or directory)
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
readv(3, [{"", 0}, {"root:x:0:0:root:/root:/bin/ash\nb"..., 1024}], 2) = 1024
lseek(3, -993, SEEK_CUR)                = 31
close(3)                                = 0
open("/etc/tcb/root/shadow", O_RDONLY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/etc/shadow", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
readv(3, [{"", 0}, {"root:::0:::::\nbin:!::0:::::\ndaem"..., 1024}], 2) = 454
lseek(3, -440, SEEK_CUR)                = 14
close(3)                                = 0
ioctl(0, TIOCGWINSZ, {ws_row=46, ws_col=213, ws_xpixel=0, ws_ypixel=0}) = 0
readlink("/proc/self/fd/0", "/3", 32)   = 2
stat("/3", 0x7fff15e703c8)              = -1 ENOENT (No such file or directory)
ioctl(1, TIOCGWINSZ, {ws_row=46, ws_col=213, ws_xpixel=0, ws_ypixel=0}) = 0
writev(1, [{"Cannot access '/3': No such file"..., 45}, {"\r\n", 2}], 2Cannot access '/3': No such file or directory
) = 47

I don't have Alpine Linux bare-metal installation at the moment, so I am not sure whether the bug is in upstream or it is related only to Docker.

P.S. screen on Ubuntu image works just fine, as well as tmux on Alpine Linux image.

/cc @ncopa

question

All 16 comments

This works on my VM. I wonder if it is related to https://busybox.net/FAQ.html#job_control.

On the working VM strace has a proper pseudo TTY link:

# strace -vv -ff screen
...
[pid  8735] readlink("/proc/self/fd/3", "/dev/pts/0", 32) = 10
...
# ls -al /proc/self/fd/0
lrwx------    1 root     root            64 Apr 19 03:44 /proc/self/fd/0 -> /dev/pts/0

Not sure a good way to solve this yet.

@andyshinn Just to confirm, were you able to reproduce the issue in a Docker container?

To me, it looks like screen gets an empty string path instead of /dev/pts and join it with a pty number. By the way, I have only /dev/pts/ptmx device inside docker containers (both in Ubuntu and in Alpine Linux).

@frol I can reproduce in docker and it does not happen on my bare-metal alpine desktop. something weird is going on.

I am also able to reproduce this.

I am using Vagrant with this box: maier/alpine-3.3-x86_64. I am also using the vagrant-alpine plugin.
My docker version: Docker version 1.11.1, build v1.11.1

Here are my results of the exploratory commands that @andyshinn mentioned (note lack of readlink for strace):

bash-4.3# strace -vv -ff screen
execve("/usr/bin/screen", ["screen"], ["HOSTNAME=4faa17cd6d7a", "GPG_KEY=C01E1CAD5EA2C4F0B8E35715"..., "TERM=xterm", "PYTHON_VERSION=2.7.11", "PATH=/usr/local/sbin:/usr/local/"..., "PWD=/", "LANG=C.UTF-8", "PYTHON_PIP_VERSION=8.1.2", "SHLVL=1", "HOME=/root", "_=/usr/bin/strace"]) = 0
arch_prctl(ARCH_SET_FS, 0x6a2482899da8) = 0
set_tid_address(0x6a2482899de0)         = 20
open("/etc/ld-musl-x86_64.path", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/lib/libncursesw.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/libncursesw.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/usr/lib/libncursesw.so.6", O_RDONLY|O_CLOEXEC) = 3
fcntl(3, F_SETFD, FD_CLOEXEC)           = 0
fstat(3, {st_dev=makedev(8, 3), st_ino=136041, st_mode=S_IFREG|0755, st_nlink=54, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=680, st_size=346608, st_atime=2015/12/18-16:06:04, st_mtime=2015/12/18-16:06:04, st_ctime=2016/05/28-23:56:30}) = 0
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220e\1\0\0\0\0\0"..., 960) = 960
mmap(NULL, 2445312, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) = 0x6a24823bc000
mmap(0x6a248260b000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x4f000) = 0x6a248260b000
close(3)                                = 0
mprotect(0x6a248260b000, 20480, PROT_READ) = 0
mprotect(0x6a2482898000, 4096, PROT_READ) = 0
mprotect(0x249340c7000, 4096, PROT_READ) = 0
prlimit64(0, RLIMIT_NOFILE, NULL, {rlim_cur=1024*1024, rlim_max=1024*1024}) = 0
close(1048575)                          = -1 EBADF (Bad file descriptor)
...snip lots of repeated lines...
close(1045394)                          = -1 EBADF (Bad file descriptor)^C
--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL, si_value={int=2206380829, ptr=0xa228382b31d}} ---
Process 20 detached

and:

bash-4.3# ls -lah /proc/self/fd
total 0
dr-x------    2 root     readproc       0 May 29 00:41 .
dr-xr-x---    7 root     readproc       0 May 29 00:41 ..
lrwx------    1 root     root          64 May 29 00:41 0 -> /6
lrwx------    1 root     root          64 May 29 00:41 1 -> /6
lrwx------    1 root     root          64 May 29 00:41 2 -> /6
ls: /proc/self/fd/3: cannot read link: No such file or directory
lr-x------    1 root     root          64 May 29 00:41 3

As the container is running here are some relevant inspected values:

            "AttachStdin": true,
            "AttachStdout": true,
            "AttachStderr": true,
            "Tty": true,
            "OpenStdin": true,
            "StdinOnce": true,

Contents of my dev dir:

bash-4.3# ls -lathr /dev
total 4
crw-rw-rw-    1 root     root        1,   5 May 29 00:33 zero
crw-rw-rw-    1 root     root        1,   9 May 29 00:33 urandom
crw-rw-rw-    1 root     root        5,   0 May 29 00:33 tty
lrwxrwxrwx    1 root     root          15 May 29 00:33 stdout -> /proc/self/fd/1
lrwxrwxrwx    1 root     root          15 May 29 00:33 stdin -> /proc/self/fd/0
lrwxrwxrwx    1 root     root          15 May 29 00:33 stderr -> /proc/self/fd/2
drwxrwxrwt    2 root     root          40 May 29 00:33 shm
crw-rw-rw-    1 root     root        1,   8 May 29 00:33 random
drwxr-xr-x    2 root     root           0 May 29 00:33 pts
lrwxrwxrwx    1 root     root           8 May 29 00:33 ptmx -> pts/ptmx
crw-rw-rw-    1 root     root        1,   3 May 29 00:33 null
drwxrwxrwt    2 root     root          40 May 29 00:33 mqueue
crw-rw-rw-    1 root     root       10, 229 May 29 00:33 fuse
crw-rw-rw-    1 root     root        1,   7 May 29 00:33 full
lrwxrwxrwx    1 root     root          13 May 29 00:33 fd -> /proc/self/fd
drwxr-xr-x    1 root     root        4.0K May 29 00:33 ..
drwxr-xr-x    5 root     root         360 May 29 00:33 .
crw-------    1 root     root      136,   6 May 29 00:36 console

For what it's worth, tmux works fine.

Also reproducible with alpine using Docker for Mac:

$ docker run -it --rm alpine sh
/ # apk --update -q --no-progress add screen && screen
Cannot access '/4': No such file or directory
/ #

In which 4 varies randomly among 0, 1, 2, 4, etc.

@marcosnils Checked with Docker 17.03. Now, neither screen nor tmux work... Awesome change!

$ docker run -it --rm --privileged alpine sh
/ # apk add --no-cache screen tmux

/ # screen
Must be connected to a terminal.

/ # tmux
lost server

@frol the rason why it was working in alpine 3.4 was before some hacks that were corrected. Now that things should work as expected, it's broken due to docker/docker#8755. Should be fixed natively whenver docker updates the current runC version.

@marcosnils Docker 17.03 is released with runC from January 29th and I assumed that since the runC PR was merged on December 8th, it should be already in this Docker 17.03 release.

@frol even though 17.03 is recent, docker is still using an old vendored runC version https://github.com/docker/docker/tree/master/vendor/github.com/opencontainers/runc that doesn't have that patch.

@marcosnils OK, thank you for clarification. I will check with the next major release then.

@frol if you read docker/docker#8755, you'll see that you can hack around this by using the script command.

Just tested on a recent build of Docker master, and can confirm that both screen and tmux from Alpine 3.5 work as expected! (and thus will be fixed in Docker 17.06+)

awesome @tianon. Thx for that!

@frol can you close this one now?

I confirm that everything works fine in Docker 17.06!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dinogun picture dinogun  路  3Comments

kalaksi picture kalaksi  路  3Comments

rmNyro picture rmNyro  路  4Comments

gliptak picture gliptak  路  4Comments

kooksee picture kooksee  路  4Comments