Using bin inside container

Hopefully this is an easy question, but please use kid gloves, because my container knowledge is zero thus far.

I am trying to provide an older version of a binary/package on Ubuntu 20.04, by using a 16.04 lxc container. Here are my steps for standing up my container.

$ multipass launch focal -n lixc ; multipass shell lixc
$ lxd init
$ lxc launch ubuntu:16.04 $lxcname ; lxc shell $lxcname
# apt update ; apt -y dist-upgrade ; apt -y install $myapp

$ lxd init --dump
config: {}
    networks: []
storage_pools:
- config:
    source: /var/snap/lxd/common/lxd/storage-pools/default
  description: ""
  name: default
  driver: dir
profiles:
- config: {}
  description: Default LXD profile
  devices:
    eth0:
      name: eth0
      nictype: macvlan
      parent: enp0s2
      type: nic
    root:
      path: /
      pool: default
      type: disk
  name: default

I used the dir storage pool, no bridged networking, and more or less the defaults where possible.
The goal is to have a deployable container, with no networking requirements, to just run on a host system and take data in and spit data out from the package that I installed in the container.

I’ve got the container up and running with the package(s) I need, but I’m trying to figure out how to work with the container’s binary from the host system.

What I’m trying to do:

$ myapp $localinfile > $localoutfile

Ive tried using

$ lxc exec $lxcname $myapp $localinfile > $localoutfile
and
$ lxc-execute -n $lxcname $myapp $localinfile > $localoutfile

I then tried to pass through a working directory for in/out files.

$ lxc config device add $lxcname dir1 disk source=/tmp/passthru/ path=/passthru
$ lxc exec $lxcname $appname /passthru/$infile > /passthru/$outfile
-bash: /passthru/$outfile: No such file or directory #this makes sense, I'll try to change output to host dir
$ lxc exec $lxcname '$appname /passthru/$infile' > /tmp/passthru/$outfile #no output, it zeros out the $infile oddly enough, so *something* is happening
$ lxc exec $lxcname $appname /passthru/$infile #this prints a bunch of output, because the outfile is a png image, so this appears to be working.

If I shell into the container using `lxc shell $lxcname, I can then cd to /passthru and run the command like normal $myapp $localinfile > $localoutfile and it runs just fine.
This is the same for both the root user, which is the default shell user, and if I su to the Ubuntu user.
The passthru directory inside the container is owned by nobody:nogroup, despite the directory in the host being owned by ubuntu:ubuntu, ubuntu being the default user in the vm I’m using to test lxc on.
I have the passthru directory 777’d.

I tried specifying the uid to run as (1000), and tried forcing a non-interactive terminal, and also turned on the debug flag, but I’m not entirely sure how to figure out which rabbit hole to go down.

Linking pastebin of debug output in hopes someone can easily eyeball what I’m missing.
I imagine it’s some sort of logical disconnect in my mind having not dealt with containers, so hopefully this can demystify that for me.

TIA

Hi!

First, there is a difference between LXC and LXD. Commands like lxc-execute are LXC, while lxc exec are LXD. If you are a new user, it makes sense to stick to LXD because it is more user-friendly. More on this at https://blog.simos.info/comparison-between-lxc-and-lxd/

You get stuck with using Unix shell redirection (the >), while the LXD commands are fine. The core issue is how your Unix shell interprets the >, whether it refers to the command on the host, or whether you can force it to run in the container. Also, when you lxc exec, does the command respect any redirection commands?

If you run the following, you do not get any output. The reason is that there is no command called ls -l /. There is a command ls but the way the following is written, is an executable name that obviously does not exist.

$ lxc exec mycontainer -- 'ls -l /'

The common workaround is to do something like this. That is, prepend bash -c and then put the actual command in quotes.

$ lxc exec mycontainer -- bash -c 'ls -l /'

Having said that, I suggest instead of using LXD, to create a snap package for your binary executable. A snap package is an executable (or more) that runs in a runtime. It only runs when you run the command.

Here is a minimal working example. Create a file called snapcraft.yaml with the following content. Make sure there is a binary/ subdirectory, and in there there is a myexe binary executable.

name: mybinary
base: 'core'
version: '1.0' 
summary: My binary in a snap package
description: |
  This is a snap package that encapsulates my binary. 
grade: stable
confinement: strict

parts:
  mybinary:
    plugin: dump
    source: ./binary/
apps:
  mybinary:
    command: myexe
    plugs: 
     - home

Then, to build the snap package, run the command

snapcraft --use-lxd

It should create a snap package called mybinary_1.0_amd64.snap. Install this snap package:

sudo snap install mybinary_1.0_amd64.snap --dangerous

Finally, run the binary executable,

$ mybinary 
Hello, world (binary executable running from within a snap package)!
$ 

Hi simos, I greatly appreciate the help.

I was fairly sure that the shell was eating the redirection at some point, which I tried to overcome with various single/double quotes to no avail.

I was somewhat able to get around this by just making a simple bash script in the passthru dir that encapsulated the redirection from within the container runtime, which did end up working.

I am intrigued by the possibility of the snap package.
Without trying to wade into the political waters of snap, this looks like exactly what I was hoping to achieve, so I will take a stab at this.
I was unaware that you could essentially write your own snaps.
I was incorrectly under the assumption that snaps were required to be published to the snap store, and thus not sideload-able. But I now think I’m merely conflating the third party repo stuff.

I will hopefully be able to report back with a working snap package soon, as this would greatly simplify things as a near drop in replacement for the issue I face.

Many thanks again for your taking the time to steer me in the correct direction.