How to get vscode working with a python virtualenv inside a LXD container

I have a LXD container with a python virtualenv in it. I’d like vscode on my host machine to use this virtualenv. So I mounted it and now I can see the virtualenv directory on my host machine and I can even activate it on my host. But vscode won’t work with it returning the following:

2023-05-18 16:42:38.353 [info] Experiment 'pythonPromptNewFormatterExt' is active
2023-05-18 16:42:38.353 [info] Experiment 'pythonPromptNewToolsExt' is active
2023-05-18 16:42:38.353 [info] Experiment 'pythonSurveyNotification' is active
2023-05-18 16:42:38.353 [info] VS Code was launched from an activated environment: 'venv', selecting it as the interpreter for workspace.
2023-05-18 16:42:38.353 [info] Test server listening.
2023-05-18 16:42:38.589 [info] > ./venv/bin/python -I ~/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/get_output_via_markers.py ~/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/interpreterInfo.py
2023-05-18 16:42:38.703 [warning] [Error: Command failed: /home/omar/Documents/code/hexr/venv/bin/python -I /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/get_output_via_markers.py /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/interpreterInfo.py
Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Python path configuration:
  PYTHONHOME = (not set)
  PYTHONPATH = (not set)
  program name = '/home/omar/Documents/code/hexr/venv/bin/python'
  isolated = 1
  environment = 0
  user site = 0
  import site = 1
  sys._base_executable = '/home/omar/Documents/code/hexr/venv/bin/python'
  sys.base_prefix = '/usr'
  sys.base_exec_prefix = '/usr'
  sys.executable = '/home/omar/Documents/code/hexr/venv/bin/python'
  sys.prefix = '/usr'
  sys.exec_prefix = '/usr'
  sys.path = [
    '/usr/lib/python38.zip',
    '/usr/lib/python3.8',
    '/usr/lib/lib-dynload',
  ]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007f89c1575740 (most recent call first):
<no Python frame>

	at ChildProcess.exithandler (node:child_process:409:12)
	at ChildProcess.emit (node:events:513:28)
	at maybeClose (node:internal/child_process:1112:16)
	at Socket.<anonymous> (node:internal/child_process:470:11)
	at Socket.emit (node:events:513:28)
	at Pipe.<anonymous> (node:net:757:14)] {
  code: 1,
  killed: false,
  signal: null,
  cmd: '/home/omar/Documents/code/hexr/venv/bin/python -I /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/get_output_via_markers.py /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/interpreterInfo.py'
}
2023-05-18 16:42:38.712 [info] > ./venv/bin/python ~/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/get_output_via_markers.py ~/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/interpreterInfo.py
2023-05-18 16:42:38.727 [error] [Error: Command failed: /home/omar/Documents/code/hexr/venv/bin/python /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/get_output_via_markers.py /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/interpreterInfo.py
Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]
Python path configuration:
  PYTHONHOME = (not set)
  PYTHONPATH = (not set)
  program name = '/home/omar/Documents/code/hexr/venv/bin/python'
  isolated = 0
  environment = 1
  user site = 1
  import site = 1
  sys._base_executable = '/home/omar/Documents/code/hexr/venv/bin/python'
  sys.base_prefix = '/usr'
  sys.base_exec_prefix = '/usr'
  sys.executable = '/home/omar/Documents/code/hexr/venv/bin/python'
  sys.prefix = '/usr'
  sys.exec_prefix = '/usr'
  sys.path = [
    '/usr/lib/python38.zip',
    '/usr/lib/python3.8',
    '/usr/lib/lib-dynload',
  ]
Fatal Python error: init_fs_encoding: failed to get the Python codec of the filesystem encoding
Python runtime state: core initialized
ModuleNotFoundError: No module named 'encodings'

Current thread 0x00007feadb07b740 (most recent call first):
<no Python frame>

	at ChildProcess.exithandler (node:child_process:409:12)
	at ChildProcess.emit (node:events:513:28)
	at maybeClose (node:internal/child_process:1112:16)
	at Socket.<anonymous> (node:internal/child_process:470:11)
	at Socket.emit (node:events:513:28)
	at Pipe.<anonymous> (node:net:757:14)] {
  code: 1,
  killed: false,
  signal: null,
  cmd: '/home/omar/Documents/code/hexr/venv/bin/python /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/get_output_via_markers.py /home/omar/.vscode/extensions/ms-python.python-2023.8.0/pythonFiles/interpreterInfo.py'
}
2023-05-18 16:42:39.987 [info] Starting Pylance language server.

Is it that vscode doesn’t play nicely with LXD?

For reference I’ve created a lxc profile using this script. Which mounts my home directory so that I can access it in the container and so that the container can write to it.

Hi @omar-selo

Please can you expand a bit on this statement. Ideally showing the specific commands you are running to achieve it. As I do not quite follow what you are doing here.

Thanks

I ran this script to generate a profile “omar” that will mount my home directory. After that I created a container using lxc launch ubuntu:18.04 hexr -p default -p omar. Inside the container I created a python virtualenv in some directory “venv”. Then outside the container I could actually activate this virtualenv on my host machine using source venv/bin/python

Ah right, I see, you’re not mounting the container back to the host, but instead mounting your home directory into the container, and then creating files (the virtualenv) inside the container but using your mounted home directory.

Now this is where my knowledge is weak, because I no next to nothing about Python or virtualenv.
However one thing I can suggest you could try is enabling UID shifting on the mount so that your uids inside the container align with the host (and vice versa).

Although this will require that you have the same user (with same uid/gid) inside the container as you’re using on the host.

Then you can do:

lxc profile device set <profile> home shift=true

Ok if I understood you correctly. I first checked that my uid and gid is the same on my host machine and container through id command. Then I ran lxc profile device set omar home shift=true. But I got the following:

Error: The following instances failed to update (profile change still saved):
 - Project: default, Instance: hexr: Failed to start device "home": Required idmapping abilities not available

What host OS/version are you running on, and what is the filesystem of your home directory?

For reference I installed LXD using snap install lxd and initialized it using lxd init --auto. My OS is Ubuntu 22.04.2 and my filesystem is ZFS

Are OK, so ZFS doesn’t support idmapped mounts (yet), try enabling shiftfs (which is the non-mainlined precursor to idmapped mounts):

sudo snap set lxd shiftfs.enable=true
sudo systemctl reload snap.lxd.daemon

See Trying out `shiftfs`

Ok after running:

sudo snap set lxd shiftfs.enable=true
sudo systemctl reload snap.lxd.daemon

I ran lxc profile device set omar home and it worked!
I also ran from the link you shared:

lxc config set hexr security.privileged true
lxc restart hexr
lxc config unset hexr security.privileged
lxc restart hexr

But sadly I still get the same error in vscode

You should avoid using privileged containers.

Perhaps its an issue with the path to the virtualenv inside the container is different to that on the host.

Can you try and narrow down the error more?

The other thing you could try rather than mounting your home directory into the container, is creating the virtualenv directly inside the container and then mounting that back to the host using:

lxc file mount <instance>/path/in/container /path/on/host

Since you’re suggesting the use of unprivileged containers, I’m assuming that an ordinary user is executing commands, but doesn’t mount require root privileges unless the path is specified in /etc/fstab with the user option?

Edit: maybe never mind, as presumably the lxc command always has access to privilege escalation.

You will need to use sudo to mount locally as lxc doesnt have root access (lxc is client to lxd which does have root access).

But this is very different from running your container privileged which allows the workloads in your container to access the host.

1 Like