vscode Dockerfile with more security over X-11 without requiring --net=host and or --privileged.

In this quick guide we go over the pitfalls of attempting to get vscode to work inside a docker container over the X-11 session which is preferred over vnc and other options such as xhost+

vscode Dockerfile with more security over X-11 without requiring --net=host and or --privileged.
Credit unsplash.com

In this quick Dockerfile example we setup a more secure vscode with password change on first login. We also do not want to give this container --privileged and or --net=host option(s) as that gets messy.


  • Download your latest vscode and it is installed with dpkg -i /files/vscode.deb which we add to the Dockerfile script.
  • Two users are added root and docker with default passwords 'Docker!'
  • Adding the 'chage -d 0 root && chage -d 0 docker' will force a password change on first login.
  • X-11 works and without requiring --net=host and or --privileged. We do not want --net=host as the containers open ports will now be 'blended' with the host system and as soon as you add more containers that is just a mess. Additionally from a security standpoint why have --privileged if you can reduce and limit a containers access?
FROM ubuntu:latest
ENV RED='\e[1;33m'
ENV CLR='\e[0m'

RUN printf "${RED}RUN apt-get update ${CLR}\n"
RUN apt-get update -y

RUN printf "${RED} RUN ap-get install -y wget build-essential checkinstall${CLR}\n"
RUN DEBIAN_FRONTEND=noninteractive apt-get -y upgrade
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y xserver-xorg-core xserver-xorg wget build-essential nma>
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y xorg systemctl openssh-server openssh-client iproute2 l>

# Add in root:Docker!  and docker:Docker - set password for reset
RUN echo "root:Docker!" | chpasswd
RUN adduser docker
RUN echo "docker:Docker!" | chpasswd
RUN chage -d 0 root && chage -d 0 docker

RUN apt-get update -y
RUN apt-get install -y software-properties-common --fix-missing
RUN apt-get install -y apt-utils

#python installation
RUN add-apt-repository ppa:deadsnakes/ppa
RUN apt-get install -y python3-pip python3.10

RUN mkdir -p /files

COPY sshd_config /etc/ssh/

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libc6-x32 zip unzip nano vim libc6-i386 rsync curl
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y libc6-i386

COPY *.deb /files/

# Adding in vscode here
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y xdg-utils libasound2
RUN DEBIAN_FRONTEND=noninteractive dpkg -i /files/vscode.deb
RUN DEBIAN_FRONTEND=noninteractive curl -fsSL https://code-server.dev/install.sh | sh

ENTRYPOINT service ssh restart && bash

When we copy the sshd_config we make two important modifications:

Port 222

# and very important change
#x11UseLocalhost yes to
X11UseLocalhost no 

When you change X11UseLocalhost to active [no] you can set an external DISPLAY=$IP:$PORT of the main calling server. But you MUST set this from the root account when the container is up.

Once you have this built with:

docker build . -t vscode

One can run it without requiring --net=host and or --privileged.  Start up the container and login as root:

docker run -it -d --p 2000:22 --name=vscode vscode

From the main server we can inspect the ip and DISPLAY variable:

echo $DISPLAY && ip addr

With our valule of we set this inside the container:

export DISPLAY=

An interesting thing will happen on your first login as user docker - it will force a password change then immediately kick you back out. But on your second login it will now work:

  • Every time you login it will change $DISPLAY to the local namespace of the docker container
  • User 'docker'  requires command line arguments to get working, note!
code --no-sandbox --user-data-dir=/home/docker/
  • You will get complaints from vscode
  • You will get crashes - vscode inside a docker over X-11 seemed to crash often - but when run again it would work.
  • Does vscode play nice?  Not sure - sometimes it would have internet access and the next time it did not seem to be able to access the plugins. It has a strange history of just uninstalling itself - in a docker container it can try but naturally you just replay the cartridge so it doesn't get that option.
  • It is a working container - but at this time kinda problematic.
Linux Rocks Every Day