Skip to main content

A lightweight pure-python container implementation

Project description

A lightweight pure-python container implementation.

It is a wrapper around the Linux namespace functionality through libc functions like unshare(), nsenter() and mount(). You can think of it as a sturdier chroot replacement, where cleanup is easy (no lingering processes or leaked mountpoints). It needs superuser privileges to run.

Usage

Installation

You can either install it with pip:

pip3 install furnace

Or if you want, the following commands will install the bleeding-edge version of furnace to your system.

git clone https://github.com/balabit/furnace.git
cd furnace
python3 setup.py install

This will of course install it into a virtualenv, if you activate it beforehand.

Dependencies

The only dependencies are:

  • Python3.5+

  • Linux kernel 2.6.24+

  • A libc that implements setns() and nsenter() (that’s basically any libc released after 2007)

Example

After installing, the main interface to use is the ContainerContext class. It is, as the name suggests, a context manager, and after entering, its run() and Popen() methods can be used exactly like subprocess’s similarly named methods:

from furnace.context import ContainerContext

with ContainerContext('/opt/ChrootMcChrootface') as container:
    container.run(['ps', 'aux'])

The above example will run ps in the new namespace. It should show two processes, furnace’s PID1, and the ps process itself. After leaving the context, furnace will kill all processes started inside, and destroy the namespaces created, including any mountpoints that were mounted inside (e.g. with container.run(['mount', '...'])).

Of course, all other arguments of run() and Popen() are supported:

import sys
import subprocess
from furnace.context import ContainerContext

with ContainerContext('/opt/ChrootMcChrootface') as container:
    ls_result = container.run(['ls', '/bin'], env={'LISTFLAGS': '-la'}, stdout=subprocess.PIPE, check=True)
    print('Files:')
    print(ls_result.stdout.decode('utf-8'))

    file_outside_container = open('the_magic_of_file_descriptors.gz', 'wb')
    process_1 = container.Popen(['cat', '/etc/passwd'], stdout=subprocess.PIPE)
    process_2 = container.Popen(['gzip'], stdin=process_1.stdout, stdout=file_outside_container)
    process_2.communicate()
    process_1.wait()

As you can see, the processes started can inherit file descriptors from each other, or outside the container, and can also be managed from the python code outside the container, if you wish.

As a convenience feature, the context has an interactive_shell() method that takes you into bash shell inside the container. This is mostly useful for debugging:

import traceback
from furnace.context import ContainerContext

with ContainerContext('/opt/ChrootMcChrootface') as container:
    try:
        container.run(['systemctl', '--enable', 'nginx.service'])
    except Exception as e:
        print("OOOPS, an exception occured:")
        traceback.print_exc(file=sys.stdout)
        print("Entering debug shell")
        container.interactive_shell()
        raise

Development

Contributing

We appreciate any feedback, so if you have problems, or even suggestions, don’t hesitate to open an issue. Of course, Pull Requests are extra-welcome, as long as tests pass, and the code is not much worse than all other existing code :)

Setting up a development environment

To set up a virtualenv with all the necessary tools for development, simply run

make dev

This will create a virtualenv in a directory named .venv. This virtualenv is used it for all other make targets, like check

Running tests

During and after development, you usually want to run both coding style checks, and integration tests:

make lint
make check

Please make sure at least these pass before submitting a PR.

License

This project is licensed under the GNU LGPLv2.1 License - see the LICENSE.txt for details

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

furnace-0.0.3.tar.gz (22.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

furnace-0.0.3-py3-none-any.whl (23.1 kB view details)

Uploaded Python 3

File details

Details for the file furnace-0.0.3.tar.gz.

File metadata

  • Download URL: furnace-0.0.3.tar.gz
  • Upload date:
  • Size: 22.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for furnace-0.0.3.tar.gz
Algorithm Hash digest
SHA256 06c81f71de735f33900dce21b7902bdc5e3eb9d065e877fbdc33864a6d8970c4
MD5 00687608ba9088e14e5ee19472c76e7f
BLAKE2b-256 e490d26a15d528be0697b0622befe16b82ced8e729f73cd85e53112b55ce5282

See more details on using hashes here.

File details

Details for the file furnace-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: furnace-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 23.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.6.3 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for furnace-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 be418d8c2b3ea2b25f1ab74926b0c5fc0614575bb75e7eee2028dbc6996af6a3
MD5 6cc7f333f043d1e81845f6708c8ad9af
BLAKE2b-256 009944fec60b294d133936850caf546bfae04b53effa72e106232cb09c592a7b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page