Devcontainer Setup

Hey,

I did the steps to enable developer mode,
But I still get an error from opening any devcontainer on VSCode

[2203 ms] Command failed: docker ps -q -a --filter label=vsc.devcontainer.volume.name=universal --filter label=vsc.devcontainer.volume.folder=universal
[2255 ms] Exit code 1
[2259 ms] Command failed: node /root/.vscode-remote-containers/dist/dev-containers-cli-0.368.0/dist/spec-node/devContainersSpecCLI.js read-configuration --workspace-folder /workspaces/universal --id-label vsc.devcontainer.volume.name=universal --id-label vsc.devcontainer.volume.folder=universal --log-level debug --log-format json --mount-workspace-git-root
[2259 ms] Exit code 1

Do you know how to fix it?

dev.containers.dockerPath

Should it be “podman”, “docker”, or something else?

I prefer the deamon-less approach of Podman, if that would be possible

The error was made with “podman

I will test with “docker(It’s taking more than an hour to download the universal image, and it’s not even finished)

When you say you prefer the daemonless approach where did you put the command?

It should be podman if setup as a daemon but I’m guessing it isn’t finding it and defaulting to docker. It looks like you’re switching to root in the container? What is your full devcontainer.json? Did you switch docker-compose to podman-compose?

I’d used whereis podman and put the whole directory in there. same for podman-compose,

Also under your devcontainer.json I’d put this under workspace-folder:
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "containerUser": "vscode"

Also post the results of podman info
And podman --config

At the bottom of the devcontainer.json file this might also help:

 "runArgs": [
   "--userns=keep-id:uid=1000,gid=1000"
 ],
 "containerUser": "vscode",
 "updateRemoteUserUID": true,
 "containerEnv": {
   "HOME": "/home/vscode"
 }

When you say you prefer the daemonless approach where did you put the command?

I didn’t input any command (other than command pallet and modals after that).
I simply prefer the deamon-less approach Podman is proposing over Docker

It should be podman if setup as a daemon but I’m guessing it isn’t finding it and defaulting to docker

Podman is deamon-less, yes; When it failed, I tested with “podman”, now, i’m testing with “docker” but it’s been more than an hour that the container is downloading parts.

What is your full devcontainer.json?

It’s a new devcontainer (using the universal image) (see bellow)

Did you switch docker-compose to podman-compose?

I didn’t input a single command nor changed anything in Bluefin, I’m quite new to the dx part of Bluefin

I’d used whereis podman and put the whole directory in there. same for podman-compose

I was used to put “podman” or “docker” on Windows and it kinda worked, I think it was what was recommended in some docs I’d seen back then

malix@malix-pc ~> whereis podman
podman: /usr/bin/podman /usr/libexec/podman /usr/share/man/man1/podman.1.gz
malix@malix-pc ~> podman info
host:
  arch: amd64
  buildahVersion: 1.35.4
  cgroupControllers:
  - cpu
  - io
  - memory
  - pids
  cgroupManager: systemd
  cgroupVersion: v2
  conmon:
    package: conmon-2.1.10-1.fc40.x86_64
    path: /usr/bin/conmon
    version: 'conmon version 2.1.10, commit: '
  cpuUtilization:
    idlePercent: 86.62
    systemPercent: 4.52
    userPercent: 8.86
  cpus: 16
  databaseBackend: sqlite
  distribution:
    distribution: fedora
    variant: silverblue
    version: "40"
  eventLogger: journald
  freeLocks: 2032
  hostname: malix-pc
  idMappings:
    gidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 524288
      size: 65536
    uidmap:
    - container_id: 0
      host_id: 1000
      size: 1
    - container_id: 1
      host_id: 524288
      size: 65536
  kernel: 6.8.10-300.fc40.x86_64
  linkmode: dynamic
  logDriver: journald
  memFree: 257966080
  memTotal: 14489669632
  networkBackend: netavark
  networkBackendInfo:
    backend: netavark
    dns:
      package: aardvark-dns-1.10.0-1.fc40.x86_64
      path: /usr/libexec/podman/aardvark-dns
      version: aardvark-dns 1.10.0
    package: netavark-1.10.3-3.fc40.x86_64
    path: /usr/libexec/podman/netavark
    version: netavark 1.10.3
  ociRuntime:
    name: crun
    package: crun-1.15-1.fc40.x86_64
    path: /usr/bin/crun
    version: |-
      crun version 1.15
      commit: e6eacaf4034e84185fd8780ac9262bbf57082278
      rundir: /run/user/1000/crun
      spec: 1.0.0
      +SYSTEMD +SELINUX +APPARMOR +CAP +SECCOMP +EBPF +CRIU +LIBKRUN +WASM:wasmedge +YAJL
  os: linux
  pasta:
    executable: /usr/bin/pasta
    package: passt-0^20240510.g7288448-1.fc40.x86_64
    version: |
      pasta 0^20240510.g7288448-1.fc40.x86_64
      Copyright Red Hat
      GNU General Public License, version 2 or later
        <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
      This is free software: you are free to change and redistribute it.
      There is NO WARRANTY, to the extent permitted by law.
  remoteSocket:
    exists: false
    path: /run/user/1000/podman/podman.sock
  security:
    apparmorEnabled: false
    capabilities: CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SETUID,CAP_SYS_CHROOT
    rootless: true
    seccompEnabled: true
    seccompProfilePath: /usr/share/containers/seccomp.json
    selinuxEnabled: true
  serviceIsRemote: false
  slirp4netns:
    executable: /usr/bin/slirp4netns
    package: slirp4netns-1.2.2-2.fc40.x86_64
    version: |-
      slirp4netns version 1.2.2
      commit: 0ee2d87523e906518d34a6b423271e4826f71faf
      libslirp: 4.7.0
      SLIRP_CONFIG_VERSION_MAX: 4
      libseccomp: 2.5.3
  swapFree: 8581541888
  swapTotal: 8589930496
  uptime: 2h 22m 8.00s (Approximately 0.08 days)
  variant: ""
plugins:
  authorization: null
  log:
  - k8s-file
  - none
  - passthrough
  - journald
  network:
  - bridge
  - macvlan
  - ipvlan
  volume:
  - local
registries:
  search:
  - registry.fedoraproject.org
  - registry.access.redhat.com
  - docker.io
  - quay.io
store:
  configFile: /var/home/malix/.config/containers/storage.conf
  containerStore:
    number: 11
    paused: 0
    running: 3
    stopped: 8
  graphDriverName: overlay
  graphOptions: {}
  graphRoot: /var/home/malix/.local/share/containers/storage
  graphRootAllocated: 1022844993536
  graphRootUsed: 28022247424
  graphStatus:
    Backing Filesystem: btrfs
    Native Overlay Diff: "true"
    Supports d_type: "true"
    Supports shifting: "false"
    Supports volatile: "true"
    Using metacopy: "false"
  imageCopyTmpDir: /var/tmp
  imageStore:
    number: 13
  runRoot: /run/user/1000/containers
  transientStore: false
  volumePath: /var/home/malix/.local/share/containers/storage/volumes
version:
  APIVersion: 5.0.3
  Built: 1715299200
  BuiltTime: Fri May 10 02:00:00 2024
  GitCommit: ""
  GoVersion: go1.22.2
  Os: linux
  OsArch: linux/amd64
  Version: 5.0.3
malix@malix-pc ~ [125]> podman --config
Error: flag needs an argument: --config

I don’t know which argument is required thought

At the bottom of the devcontainer.json file this might also help:

I didn’t think it was needed for a basic universal image

By the way, by the time I wrote this comment, my “docker” devcontainer finished fine, but in 6263575 ms.

.devcontainer/devcontainer.json

// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/universal
{
	"name": "Default Linux Universal",
	// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
	"image": "mcr.microsoft.com/devcontainers/universal:2-linux"

	// Features to add to the dev container. More info: https://containers.dev/features.
	// "features": {},

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Use 'postCreateCommand' to run commands after the container is created.
	// "postCreateCommand": "uname -a",

	// Configure tool-specific properties.
	// "customizations": {},

	// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
	// "remoteUser": "root"
}

Okay so it works with Docker.

My problem now is that it doesn’t work with Podman, or at least not “out of the box” by using the command pallet; which is expected only when using daemon (and root) required features, such as compose, docker-in-docker, etc…

I don’t remember that was a required step on Windows.
I may be wrong, but I can’t test it anymore.

Maybe related:

I think it is the way that it is setup so both can work, due to SELinux. I asked about daemonless because I don’t know what your socket is setup as, for podman it should be:

/run/user/1000/podman/podman.sock

You can tell by running:

$(systemctl --user is-active podman.socket) so it is running as 1000, your UID. You got rid of the remoteuser="root"

You can see it is pretty common to put remoteUser: “vscode” so it isn’t set to ROOT’s PUID of 0 where SELinus will bomb out and say you’re not root you can’t do that.

Until recently rootless/root Dockerfiles didn’t exist like Podman so it wasn’t a “big deal” but SELinux see you as 1000 trying to execute as root and will bomb out. There’s ways around it like putting a :Z on the end of volume but that’s cheating basically. I don’t think you need runas anymore as it looks like someone wrote a script to do it but I don’t know enough about workspace folders and ‘–mount-workspace-git-root’ to know if that helps. Plus if you put it online and somone isn’t using BlueFin and doesn’t have that injection they’ll have issues.

Docker and Podman evolved in two different ways and Docker before SELinux I believe. I think if you install Docker Desktop it further screws things up but I don’t know. Things are changing quickly. Google has qVsisor that acts as a hypervisor that solves these issues and uses it on all their docker containers and apps. So much so they’re disable SELinux scanning objects.

Edit: Oh daemons were in the 60s init running on process 1 so they were root. Systemd and I’m guessing other non-init processes that aren’t systemd run as whatever user you want them too. Docker now will create it as root but if you to -ls a inaiswe the container the user will say room but have a PUID of 1.

I wouldn’t be afraid of installing things like Podman as systemctl --user podman.socket It’ll all show up as if you created if you init into the container. I bet docker created files as root for historical purposes. But if you go into the container and look it’ll say room with a PUID of 3432 or something. More importantly it won’t be 1 and SELinux won’t complain. Just a guess.

So what should be the default minimal addition to .devcontainer/devcontainer.json file to make Podman run on SELinux ?

So far I’ve seen 3 versions (excluding the :Z variant which, as you said, is basically cheating), but I don’t know which is the best, and what some options really does and why do they work

  1. vscode docs

    "runArgs": [
    	"--userns=keep-id"
    ],
    "containerEnv": {
    	"HOME": "/home/node"
    }
    
  2. universal blue - devcontainer setup

    "runArgs": [
    	"--userns=keep-id:uid=1000,gid=1000"
    ],
    "containerUser": "vscode",
    "updateRemoteUserUID": true,
    "containerEnv": {
    	"HOME": "/home/vscode"
    },
    
  3. universal blue - podman support

    "runArgs": [
    	"--userns=keep-id",
    	"--security-opt=label=disable"
    ],
    "containerEnv": {
    	"HOME": "/home/vscode"
    },
    

Crosspost

Also, note that only Docker + VSCode + Devcontainers is supported

I use 2 basically so it’ll still say root but the pid will be random so not really root.

Just use Docker, Podman isn’t dead but Docker is definitely baked into so much and has advanced enough you’ll be be rebuilding these things.

If you have complex dev containers it assumes Docker, and the problems multiply. You can put these variables args in a global container.config but I don’t know where that’s at off the top of my head.