poCo: portable Containers. Create statically linked, portable binaries from container images (daemonless)


logo
poCo

Containers -> Binaries
Create statically linked, portable binaries from container images

license go report card


A simple, static golang bundler!

poCo (portable-Containers) packs and converts container images into single, portable, statically linked binaries leveraging golang native embed.

โ“ How it works

poCo is extremely simple in the design.

poCo generates and builds golang code which embeds the container content compressed as an asset. It does bundle the assets by using the native golang embed primitives. The resulting binary on the first run will extract the content over the application store and will execute the entrypoint in a pivotroot environment, without requiring special permissions.

๐Ÿ’ป Install

Download poCO from the releases and install it in your PATH. poCO releases are statically built, so no dependencies (besides golang to create bundles, are required)

๐Ÿƒ Run

poCO is a no-frills binary bundler, we will see an example of how to bundle a container image into a binary.

Requires:

  • poco installed
  • sudo
  • golang >1.17 installed in the system where are you building

poCo bundles container images available remotely or locally (by specifying --local to the bundle subcommand).

For instance to pack the alpine image into a sample binary is as simple as:

CGO_ENABLED=0 ./poco bundle --image alpine --output sample

CGO_ENABLED=0 will instruct the golang compiler behind the scenes to create a statically linked executable.

We can specify optionally a default entrypoint for the resulting binary with --entrypoint, which is by default set to /bin/sh.

You can run the --help subcommand on sample to inspect its output, and you will see there are available few options:

โฏ ./sample --help     
NAME:
   sample - sample

USAGE:
    [global options] command [command options] [arguments...]

VERSION:
   0.1

DESCRIPTION:
   sample

AUTHOR:
   sample

COMMANDS:
   exec       
   uninstall  
   help, h    Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --store value       Default application store. Empty for TMPDIR
   --entrypoint value  Default application entrypoint (default: "/bin/sh")
   --add-mounts value  Additional mountpoints
   --mounts value      Default app mountpoints (default: "/sys", "/tmp", "/run")
   --help, -h          show help
   --version, -v       print the version

The binary has some defaults that can be override during build time with bundle, to run the application (in our case, sh from alpine), just run:

./sample # spawns a new /bin/sh shell

You can also pass all the args to the entrypoint of the binary (/bin/sh), by specifying -:

./sample - -c "echo foo"

See the example/ folder for a more complete example.

Supports: CGO_ENABLED, GOOS, GOARCH, etc.

It can target all architectures supported by golang.

bundle

bundle creates a binary from a container image, it takes several options listed here:

Flag Description
--entrypoint Default binary entrypoint. This is the first binary from the container image which will be executed. It defaults to /bin/sh
--output Default binary output location
--app-description This is the description of the app that will be displayed in the resulting binary --help
--app-author This is the author of the app that will be displayed in the resulting binary --help
--app-name This is the name of the app that will be displayed in the resulting binary --help
--app-version This is the version of the app that will be displayed in the resulting binary --help. The version will be used between different binary bundles to handle upgrades.
--local Tells poco to get the container image from the local Docker daemon instead of fetching it remotely. By default poco doesn't require a Docker daemon running locally
--app-mounts A list of default mount binding for the app. The application runs in a chroot-alike environment, without access to the files of the system unless explictly mounted. Multiple mounts can be specified.
--app-store A default store for your app. This is where the bundle gets extracted before being executed, and where the real app data lives afterward on subsequent calls.
--image The container image to bundle.
--command-prefix Command prefix for auto-generated code. Usually you don't need to change that unless you are running the builds as root

Mounts

A poCo bundle runs in a sandboxed environment. To expose directories or files, the resulting binary in runtime tales the --mounts or --add-mounts option (also multiple times) to specify a list of directories or files to expose from the host environment.

While creating the binary, it is also possible to specify a default set, so the binary runs with the directory shared from the host already, this is possible by passing --app-mounts.

For instance, consider:

CGO_ENABLED=0 ./poco bundle --image alpine --output sample --app-mounts /tmp --app-mounts 'ro:/home/.bar:/home/.bar'

will create a sample binary with alpine which /tmp will be mapped rw and /home/.bar ro from the host.

Default store

Every application has a default store. By default, each application will unpack its content to a temporary directory. To change this behavior and persist data in the system which is running the app, specify a default location with --app-store.

For instance, the following will use the ~/.poco/alpine folder to unpack the bundle content on the first run:

CGO_ENABLED=0 ./poco bundle --image alpine --output sample --app-store '$HOME/.poco/alpine'

Every application can indeed be uninstalled, which just deletes the default app-store:

./sample uninstall

Metadata

Every generated bundle will have a default --help which is being displayed. It is possible to set metadata such as description, name, author, copyright that will be automatically available in the resulting binary --help.

The version is more relevant if a default --app-store is being specified. The app-version is used during the first run to determine if the installed bundle should be replaced or not.

render

render allows to render the generated golang code into a specified directory. This is might be helpful if you want to change the generated binary before build.

$ mkdir alpine
$ ./poco render --image alpine alpine
$ ls alpine/
go.mod main.go

pack

pack is an internal utility to pack directories as container images that can be docker loaded afterwards:

$ mkdir foo
$ touch foo/bar
$ poco pack myimage:tag foo --destination output.tar
$ docker load -i output.tar
$ docker push myimage:tag

pack-assets

pack-assets is an internal utility to pack assets for the bundle.

$ mkdir foo
$ touch foo/bar
$ poco pack-assets -C foo .
$ ls
assets.tar.xz

unpack

unpack is an internal utility to unpack a container image into a directory

$ mkdir alpine
$ poco unpack alpine alpine
$ ls alpine
bin etc usr ...

โš ๏ธ Notes

During build sudo is required in order to preserve container permissions.

๐Ÿ” Examples

See the examples folder or linuxbundles for a collection of popular distributions packaged or either caramel for a more complete example involving popular apps.

The pipeline builds the firefox image which can be downloaded and to run locally as a standard binary:

./firefox

To uninstall:

./firefox uninstall

๐Ÿ““ TODO

  • Multi-platform support (Windows, MacOS at least..)

โ“ Why?

ยฏ_(ใƒ„)_/ยฏ

Someone told me this wasn't possible, so here we are.

I know there is flatpak and also tons of AppImages out there and this is just yet another bundler for most of you, so to make it clear: the scope of this project is not even comparable to them.

While I was sketching this up I realized I wanted something VERY simple that doesn't gets in the way and opinionated enough that can leverage already existing container image - without the need of additional docs or specific procedures for users. This bundler might fit just simple and specific purposes - and most likely - people like me that doesn't have high end goals and rely on golang daily.

So focus of this project is - to prove a point of course - and on semplicity and portability rather than, for example, security.

And besides, let's be frank. Building bundles with go+docker is really easy to go with as a stack.

๐Ÿ““ Credits

Docker authors for the pivotroot code part, was very helpful read to get that right.

๐Ÿœ Contribution

You can improve this project by contributing in following ways:

  • report bugs
  • fix issues
  • request features
  • asking questions (just open an issue)

and any other way if not mentioned here.

๐Ÿ““ Author

poCo is released under GPL-3, Copyright Ettore Di Giacinto [email protected]

Owner
Ettore Di Giacinto
Ettore Di Giacinto
Similar Resources

Create Mermaid-Js ERD diagrams from existing tables

Mermerd Create Mermaid-Js ERD diagrams from existing tables. Features Supports PostgreSQL and MySQL Select from available schemas Select only the tabl

Dec 29, 2022

A new way to create web applications using go and sdf framework.

SDF GO A new way to create web applications using go and sdf framework Explore the docs ยป View Demo ยท Report Bug ยท Request Feature Table of Contents A

Sep 27, 2022

ReverseSSH - a statically-linked ssh server with reverse shell functionality for CTFs and such

 ReverseSSH - a statically-linked ssh server with reverse shell functionality for CTFs and such

ReverseSSH A statically-linked ssh server with a reverse connection feature for simple yet powerful remote access. Most useful during HackTheBox chall

Jan 5, 2023

Go-generics-simple-doubly-linked-list - A simple doubly linked list implemented using generics (Golang)

Welcome to Go-Generics-Simple-Doubly-Linked-List! Hi, This repository contains a

Jun 30, 2022

Boxygen is a container as code framework that allows you to build container images from code

Boxygen is a container as code framework that allows you to build container images from code, allowing integration of container image builds into other tooling such as servers or CLI tooling.

Dec 13, 2021

Kubedock is a minimal implementation of the docker api that will orchestrate containers on a Kubernetes cluster, rather than running containers locally.

Kubedock Kubedock is an minimal implementation of the docker api that will orchestrate containers on a kubernetes cluster, rather than running contain

Nov 11, 2022

Open Source runtime scanner for Linux containers (LXD), It performs security audit checks based on CIS Linux containers Benchmark specification

Open Source runtime scanner for Linux containers (LXD), It performs security audit checks based on CIS Linux containers  Benchmark specification

lxd-probe Scan your Linux container runtime !! Lxd-Probe is an open source audit scanner who perform audit check on a linux container manager and outp

Dec 26, 2022

Takes an input http.FileSystem (likely at go generate time) and generates Go code that statically implements it.

vfsgen Package vfsgen takes an http.FileSystem (likely at go generate time) and generates Go code that statically implements the provided http.FileSys

Dec 18, 2022

Takes an input http.FileSystem (likely at go generate time) and generates Go code that statically implements it.

vfsgen Package vfsgen takes an http.FileSystem (likely at go generate time) and generates Go code that statically implements the provided http.FileSys

Dec 18, 2022

โ›ต EdgeVPN: the immutable, decentralized, statically built VPN. NO central server!

โ›ต EdgeVPN Fully Decentralized. Immutable. Portable. Easy to use Statically compiled VPN Usage Generate a config: ./edgevpn -g config.yaml Run it on

Jan 3, 2023

Simple API that returns JSON of statically defined

GOLANG API This is a simple example of a Go API using: Docker Docker-compose Built in go packages How to run using Docker-compose (Easiest) Clone repo

Nov 2, 2021

Operator Permissions Advisor is a CLI tool that will take a catalog image and statically parse it to determine what permissions an Operator will request of OLM during an install

Operator Permissions Advisor is a CLI tool that will take a catalog image and statically parse it to determine what permissions an Operator will request of OLM during an install. The permissions are aggregated from the following sources:

Apr 22, 2022

Show dependency graph of docker images/containers

Show dependency graph of docker images/containers

docker-graph Show dependency graph of docker images/containers like this: Orange is images and green is containers. Features Collect docker images, co

Feb 7, 2022

Identify containers at runtime and observe them. No container runtime required. Read only access to the kernel.

Linux Telemetry The Double Slit Experiment Taken from an interesting physics anomaly where the behavior of a physical system mutates simply by being o

Sep 18, 2022

Create all possible binaries from go files

Create all possible binaries from go files

nextBuild.go Create all possible binaries of a project in go ChangeLog 0.0.1 โ”€ First release. Flags You can alter a few things when creating the binar

Dec 8, 2022

Create all possible binaries from go files

Create all possible binaries from go files

nextBuild.go Create all possible binaries of a project in go ChangeLog 0.0.1 โ”€ First release. Flags You can alter a few things when creating the binar

Dec 8, 2022

Create all possible binaries from go files

gopher-build-all Create all possible binaries of a project in go ChangeLog 0.0.2 Flags bin-folder-name โ”€ With this flag you can rename the output dire

Dec 8, 2022

onnx-go gives the ability to import a pre-trained neural network within Go without being linked to a framework or library.

onnx-go gives the ability to import a pre-trained neural network within Go without being linked to a framework or library.

This is a Go Interface to Open Neural Network Exchange (ONNX). Overview onnx-go contains primitives to decode a onnx binary model into a computation b

Dec 24, 2022
Comments
  • Running firefox example on OSX

    Running firefox example on OSX

    I tried running the firefox example (build.sh) on mac - output

    [+] Building 93.9s (7/7) FINISHED
     => [internal] load build definition from Dockerfile                                                                  0.1s
     => => transferring dockerfile: 37B                                                                                   0.0s
     => [internal] load .dockerignore                                                                                     0.0s
     => => transferring context: 2B                                                                                       0.0s
     => [internal] load metadata for docker.io/library/ubuntu:latest                                                      3.0s
     => [1/3] FROM docker.io/library/ubuntu@sha256:20fa2d7bb4de7723f542be5923b06c4d704370f0390e4ae9e1c833c8785644c1      41.7s
     => => resolve docker.io/library/ubuntu@sha256:20fa2d7bb4de7723f542be5923b06c4d704370f0390e4ae9e1c833c8785644c1       0.0s
     => => sha256:20fa2d7bb4de7723f542be5923b06c4d704370f0390e4ae9e1c833c8785644c1 1.42kB / 1.42kB                        0.0s
     => => sha256:2d7ecc9c5e08953d586a6e50c29b91479a48f69ac1ba1f9dc0420d18a728dfc5 529B / 529B                            0.0s
     => => sha256:2dc39ba059dcd42ade30aae30147b5692777ba9ff0779a62ad93a74de02e3e1f 1.46kB / 1.46kB                        0.0s
     => => sha256:2b55860d4c667a7200a0cb279aec26777df61e5d3530388f223ce7859d566e7a 30.43MB / 30.43MB                     39.5s
     => => extracting sha256:2b55860d4c667a7200a0cb279aec26777df61e5d3530388f223ce7859d566e7a                             1.5s
     => [2/3] RUN apt-get update                                                                                          9.3s
     => [3/3] RUN apt-get install -y firefox &&     apt-get -y --purge autoremove                                        37.7s
     => exporting to image                                                                                                1.8s
     => => exporting layers                                                                                               1.8s
     => => writing image sha256:2051cb4cb140e52c69470b63bf48ab6d73e88f7be332edd368ffd39896b842ba                          0.0s
     => => naming to docker.io/library/firefox:latest                                                                     0.0s
     INFO  Creating bundle 'sample' (version 0.1) from image 'firefox:latest' with entrypoint '/usr/bin/firefox'
     INFO  Default mounts: /sys /tmp /run
    Password:
     INFO  Downloading image 'firefox:latest' and unpacking into 'assets' (local daemon: true)
     INFO  Creating 'assets' from '.', zst compression
    
    failure while running 'go build': # github.com/sample/sample
    ./main.go:122:20: undefined: syscall.Unshare
    ./main.go:122:36: undefined: syscall.CLONE_NEWNS
    ./main.go:131:20: undefined: syscall.Mount
    ./main.go:131:56: undefined: syscall.MS_BIND
    ./main.go:131:72: undefined: syscall.MS_REC
    ./main.go:141:20: undefined: syscall.PivotRoot
    ./main.go:152:44: undefined: syscall.MNT_DETACH
    ./main.go:172:20: undefined: syscall.Mount
    ./main.go:215:21: undefined: syscall.Mount
    ./main.go:215:59: undefined: syscall.MS_BIND
    ./main.go:215:59: too many errors
    : exit status 2
    

    Any help to get it working on OSX?

It is a clone of the CRUD operations on Instagram which can create, get, create posts and get the post along with pagination
It is a clone of the CRUD operations on Instagram which can create, get, create posts and get the post along with pagination

Instagram-API-Clone It is a basic version of a RESTful API based on Instagram where we can create user, get the users, create post and get post and ge

Jan 25, 2022
Converts an image file into various WebP images to use with img srcset

go-websizer Converts an image file into various WebP images to use with img srcset. Install $ go get github.com/pipe01/go-websizer Usage Usage of go-

Oct 7, 2021
Example golang using gin framework everything you need, i create this tutorial special for beginner.

Golang Gin Framework Fundamental Example golang using gin framework everything you need, i create this tutorial special for beginner. Feature Containe

Dec 16, 2022
Create a demo RESTful application using Golang

Instructions The goal of this exercise is to create a demo RESTful application using Golang. The Task In this task, we are building backend of an appl

Oct 30, 2021
Create a Protocol Buffers (Protobuf) plugin, which is executed with the protoc compileCreate a Protocol Buffers (Protobuf) plugin, which is executed with the protoc compile

Interview Assignment Overview You assignment is to create a Protocol Buffers (Protobuf) plugin, which is executed with the protoc compiler. In this ex

Nov 19, 2021
Create a short link

Shortlink using a GCP Cloud Run Serverless example Make a Dir: mkdir shortlink && cd shortlink Clone: git clone https://github.com/tonnytg/shortlink.

Nov 26, 2021
This application is a tool to rapidly create TFS tasks and synchronize them with wiki.

This application is a tool to rapidly create TFS tasks and synchronize them with wiki.

Jan 10, 2022
Give developers an easy way to create and integrate bank processing into their own software products
Give developers an easy way to create and integrate bank processing into their own software products

Community ยท Blog moov-io/bankcron Moov's mission is to give developers an easy way to create and integrate bank processing into their own software pro

Sep 27, 2022
Using golang framework (Gin) to create a web-application

News feeder Using golang framework (Gin) to create a web-application. This simpl

Aug 22, 2022
ging is a tool for create gin web framework development templates

ging ging is a tool for create gin web framework development templates This tool is for the freshmen who want to learn golang and gin web framework, i

Jan 15, 2022