Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to run in an existing container #34

Closed
01e9 opened this issue Mar 31, 2018 · 14 comments
Closed

How to run in an existing container #34

01e9 opened this issue Mar 31, 2018 · 14 comments
Labels

Comments

@01e9
Copy link

01e9 commented Mar 31, 2018

I see that everything runs around IMAGE. You provide an image, x11docker creates a container with proper GUI configuration and runs the app inside.


How about this scenario:

I have docker environment configured for my development project. A container for compiling the project, a container for database, a container for database management app. All these containers are managed with docker-compose. I would like x11docker to work like this: I specify a container and a command to start my IDE. Then x11docker will check if that container has the right configurations and will start successfully the command or will show me what I have to change in container parameters in order to fix the problem. Then I will add the required parameters in my docker-compose.yml, recreate the container and start my IDE via x11docker.

Does this make sense?


At the moment I set up my IDE to work inside docker container by mounting my home directory, /tmp/.X11-unix, sharing ${DISPLAY} and starting it with docker exec (I sometime execute xhost + if it shows an error).

I just found this solution on internet and I have no idea how it works (x11 noob).

Is my solution ok and I should continue using it or x11docker has to offer something better?

@mviereck
Copy link
Owner

I am not sure if I understand everything right; I am a noob with docker compose :-).

Short said, you have an already existing container and want to provide an X display only occasionally? You don't want to run from image every time?

I have early dropped preserving containers due to a docker issue. Maybe it got fixed in the meantime, but I don't think so.
If I run an image and mount a custom X socket (for example, /tmp/.X11-unix/X200) and I don't delete the container with docker option --rm, the container will persist after reboot. But the X socket X200 does not exist anymore.
From x11docker side it would not be a problem; it can create a new X200.

But docker has the annoying habit to create missing shared volumes as folders owned by root, even if the container is not running at all. In this example, after reboot there would be a folder /tmp/.X11-unix/X200 that I cannot delete without root permissions. And it forestalls the creation of a new X unix socket X200.

Maybe you don't stumble about this issue as you share the whole folder /tmp/.X11-unix instead of a single socket. For x11docker that is not an option as it creates multiple X sockets that should not be shared with other containers. x11docker wants to isolate X access between containers and host to avoid X security issues.

Is my solution ok and I should continue using it

If you don't care about X security leaks between host and container, your solution is ok.
For X access of an application, it needs access to the X socket that you share with /tmp/.X11-unix, it needs environment variable DISPLAY and an authentication to access X (that one you miss).

I sometime execute xhost + if it shows an error

This is a bad idea as it allows access to X for everyone and makes your host vulnerable.
You can either manipulate the cookie XAUTHORITY from host and share it, or you can set a more special xhost command. Do you set the same UID in container as you have as host user?
Than run xhost +SI:localuser:$(id -un).
To allow root in container access to X, run xhost +SI:localuser:root.

or x11docker has to offer something better?

x11docker offers avoidance of X security leaks and improves container isolation. If you trust your container applications, this does not matter.
Further it offers options for e.g. pulseaudio sound, clipboard sharing and hardware acceleration. If you don't need that, it doesn't matter, too.

Then x11docker will check if that container has the right configurations and will start successfully the command or will show me what I have to change in container parameters in order to fix the problem. Then I will add the required parameters in my docker-compose.yml, recreate the container and start my IDE via x11docker.

There is one possibility. x11docker offers to only create a new X server and shows what is needed to access it. Example with Xephyr:

lauscher@debian9:~$ read Xenv < <(x11docker --xephyr --showenv)
lauscher@debian9:~$ echo $Xenv
DISPLAY=:200 XAUTHORITY=/home/lauscher/.cache/x11docker/X200-/share/Xclientcookie XSOCKET=/tmp/.X11-unix/X200 XPRA_XSHM=0 X11DOCKER_CACHE=/home/lauscher/.cache/x11docker/X200-

Example with display from host:

lauscher@debian9:~$ read Xenv < <(x11docker --hostdisplay --showenv)
lauscher@debian9:~$ echo $Xenv
DISPLAY=:0.0 XAUTHORITY=/home/lauscher/.cache/x11docker/X50-/share/Xclientcookie XSOCKET=/tmp/.X11-unix/X0 XPRA_XSHM=0 X11DOCKER_CACHE=/home/lauscher/.cache/x11docker/X50-

Your container needs environment variables DISPLAY and XAUTHORITY. It needs shared volumes XAUTHORITY and XSOCKET. You can mount XAUTHORITY at a different location in container; in that case, environment variable XAUTHORITY in container must point to that location.


Do I understand right that you can subsequently add shared volumes to an already running container with docker compose? It is possible to unmount them afterwards?

@01e9
Copy link
Author

01e9 commented Mar 31, 2018

Do I understand right that you can subsequently add shared volumes to an already running container with docker compose? It is possible to unmount them afterwards?

No. Docker compose is just syntactic sugar to help you start all your configured and linked containers with one command docker-compose up instead of starting them individually with docker run. You create one file docker-compose.yml with all information about your containers (also you can create docker-compose.override.yml to override/add some keys in docker-compose.yml without changing it). Then you manage all those containers by executing the docker-compose command in the same directory.

Do you set the same UID in container as you have as host user?

Yes


Thank you very much for the detailed answer!

@01e9 01e9 closed this as completed Mar 31, 2018
@mviereck
Copy link
Owner

Just an afterthought:

You need X only for the IDE, right?
The IDE is in the same image as the rest of the development environment?
All important changing data is stored in HOME from host?
You don't need a persistant container for the IDE, you just want to start it after your developer image is already running?

Instead of executing the IDE in the same container as the rest, you can create a new container with x11docker and share the same HOME.

The following command should catch most of your IDE setup as far as I understand it:

x11docker --hostdisplay --homedir $HOME --clipboard \
    -- \
    --cap-add=SYS_PTRACE --publish=80:8080  \
    defacto:1.1  [yourIDEcommand]

Maybe you also need x11docker option --cap-default.

@01e9
Copy link
Author

01e9 commented Mar 31, 2018

This can definitely be a solution.

I also need to be in the same network created by docker-compose to be able to connect to the database container. I think this can be achieved with --network defacto_default


I simplified a bit the above command just to make the IDE start

x11docker --hostdisplay --homedir $HOME --clipboard defacto:1.1 ~/soft/phpstorm/bin/phpstorm.sh

but it throws export: dpkg-dev: bad variable name

x11docker ERROR: Docker startup seems to have failed! 

  Last lines of docker.log:
ID=debian
HOME_URL="http://www.debian.org/"
SUPPORT_URL="http://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
/x11docker/x11docker.CMD.sh: 16: export: dpkg-dev: bad variable name

  Last lines of xterm.log:
x11docker: container IP: 172.17.0.2
x11docker: container PID: 13199
mkdir: created directory '/var/run/dbus'
mkdir: created directory '/tmp/.ICE-unix'
mkdir: created directory '/tmp/.X11-unix'
mkdir: created directory '/tmp/.font-unix'
lrwxrwxrwx 1 root root 13 Mar 31 19:03 /tmp/.X11-unix/X0 -> /x11docker/X0

  Last lines of command stderr:

@mviereck
Copy link
Owner

Does the image contain environment variables defined with ENV and containing whitespaces?
x11docker does not handle that well, that is the next to-do point on my list.
Please run with --verbose and store the output at pastebin for debugging.

@01e9
Copy link
Author

01e9 commented Mar 31, 2018

There is a variable PHPIZE_DEPS containing spaces and tabs

$ docker exec defacto printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=ffd2b68e0281
DISPLAY=:0
PHPIZE_DEPS=autoconf 		dpkg-dev 		file 		g++ 		gcc 		libc-dev 		make 		pkg-config 		re2c
PHP_INI_DIR=/usr/local/etc/php
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2
PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie
GPG_KEYS=A917B1ECDA84AEC2B568FED6F50ABC807BD5DCD0 528995BFEDFBA7191D46839EF9BA0ADA31CBD89E 1729F83938DA44E27BA0F4D3DBDB397470D12172
PHP_VERSION=7.1.14
PHP_URL=https://secure.php.net/get/php-7.1.14.tar.xz/from/this/mirror
PHP_ASC_URL=https://secure.php.net/get/php-7.1.14.tar.xz.asc/from/this/mirror
PHP_SHA256=c09f0c1074f5689b492d79034adb84e6a6c6d08c6763c02282e6318d41156779
PHP_MD5=
TINI_VERSION=v0.17.0
HOME=/home/i

@mviereck
Copy link
Owner

I've made an update that handles whitespaces in ENV variables.
Please try again.
Though, that export error should not have prevented upstarting the IDE, I assume something else is going wrong.

@01e9
Copy link
Author

01e9 commented Mar 31, 2018

Now I get export: Illegal option -W

https://pastebin.com/raw/QBBnaM4d

mviereck added a commit that referenced this issue Mar 31, 2018
@mviereck
Copy link
Owner

ok, next try.
Formerly I parsed the output of docker inspect --format='{{.Config.Env}}' IMAGENAME, but in case of your image environment that is impossible. The output lacks quotation marks, and the values contain =.
Now I am parsing the output of docker run --entrypoint env IMAGENAME env.


In the pastebin log I see the image has init system tini as entrypoint. x11docker also runs tini with docker run option --init.
To have only one instance of tini, set either x11docker option --no-init or --no-entrypoint.

@01e9
Copy link
Author

01e9 commented Mar 31, 2018

It works!

x11docker --hostdisplay --homedir ${HOME} --clipboard \
    --cap-default --no-entrypoint \
    -- "--cap-add=SYS_PTRACE --publish=80:8080 --network defacto_default" \
    defacto \
    ~/soft/phpstorm/bin/phpstorm.sh

The only problem is that it generates an orphan container after every execution

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS                          PORTS                    NAMES
3e8ce56668c3        defacto             "env env"                18 seconds ago       Exited (0) 18 seconds ago                                admiring_lewin
3b7e036c9ff5        defacto             "env env"                About a minute ago   Exited (0) About a minute ago                            thirsty_jepsen
9dfc5a3dfa2c        defacto             "env env"                2 minutes ago        Exited (0) 2 minutes ago                                 optimistic_hypatia
6ee864f0574b        defacto             "env env"                3 minutes ago        Exited (0) 3 minutes ago                                 happy_agnesi
f2076f096d2d        adminer             "entrypoint.sh docke…"   3 minutes ago        Up 3 minutes                    0.0.0.0:8080->8080/tcp   defacto_adminer
634bb9e1658a        defacto             "/tini -- sleep infi…"   3 minutes ago        Up 3 minutes                    8080/tcp                 defacto
e80c79a3784a        postgres:9          "docker-entrypoint.s…"   3 minutes ago        Up 3 minutes                    5432/tcp                 defacto_pg

@mviereck
Copy link
Owner

It works!

:-)

The only problem is that it generates an orphan container after every execution

Argh! Yeah, i forgot to add --rm, is fixed now.

I also fine-tuned the parsing of the image command. Now you can set desired working directory with:

x11docker [...] defacto  sh -c "cd $PWD ; ~/soft/phpstorm/bin/phpstorm.sh"

@mviereck
Copy link
Owner

mviereck commented Apr 3, 2018

Afterthought about tini:

Although recent docker versions provide option --init to run tini in container, it does not work on all systems. At least it fails in openSUSE and fedora; its an issue with their docker packaging. Compare #23

If you want to deploy your setup and always be sure tini is running, it is more reliable to use your tini installation in image.
With --no-entrypoint you disable tini in image.
Rather use --no-init to run tini from image instead of unreliable tini from docker.

@mviereck
Copy link
Owner

mviereck commented Apr 3, 2018

I've made an update that checks for tini in ENTRYPOINT and disables it if x11docker already uses docker run option --init. (x11docker will use --init only if it is really available and disables it otherwise).

You would not need to set --no-init or --no-entrypoint now.

Though, you can stay with --no-init to avoid possible future issues with docker's --init and to be sure it is always the same tini version you are running.

@mviereck
Copy link
Owner

mviereck commented May 4, 2018

you can stay with --no-init to avoid possible future issues with docker's --init and to be sure it is always the same tini version you are running.

With latest release v4.2.0 tini in ENTRYPOINT is preferred over tini from host. Now you can drop --no-init, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants