Application containers for FreeBSD.
The goal of vessel is to expose the powerful features of the FreeBSD operating system to application, operations and test engineers. Vessel accomplishes this goal by integrating tightly with FreeBSD's system level interfaces to provide a "docker-like" interface that feels familiar to most developers. Vessel differs from other jail management systems in that it runs alongside the container listening for system events that can be used for container management and observability.
Example Integrations
- Jail process tracing with kqueue. This allows us to run "fat jails" and non-interactive jails in the foreground.
- Signal handling with kqueue. Trigger jail events (like shutdown) with signals.
- Resource control events from
devd.seqpacket
. Execute custom commands based on resource events. - Container supervisor. Start, stop and restart jails by changing runtime files in deployment directory.
- And more...
Feature | Implemented |
---|---|
VesselFile (similar to Dockerfile) | Yes |
Run configuration files (ini) | Yes |
Volume Management | Yes |
Image Push/Pull Repositories (s3) | Yes |
Jail Management | Yes |
Container Supervisor | Yes |
Resource Control | Yes |
CPU Sets | Yes |
Internal (Bridged) Networking | In Progress |
DNS Service Discovery | In Progress |
Multi-node container orchestration | Not yet |
VNET Routing via PF | In Progress |
Vessel follows a similar branching strategy as FreeBSD. The master
branch is equivalent to FreeBSD's CURRENT branch. We also maintain a stable branch. The branch you build from depends on if you want cutting edge (master) features or the most stable (stable-) features.
- Download the source from github (or clone the repository).
- Building all dependencies (including cmake) can take a long time. To expediate the process it can be useful to install the build and runtime dependencies with
pkg
. An up-to-date list of dependencies can be found in theports/Makefile
file.pkg update && pkg install curl tcl86 cmake tcllib py39-s3cmd tclsyslog
- From the source directory make the build directory:
mkdir build
- Change directory into the build dir and run cmake:
cd build
andcmake ..
- Make and install vessel
make && sudo make install
The port is maintained on the stable- branch. Building the port and all dependencies takes about 2 hours on a t3.micro so I would recommend installing the dependencies via packages. Port install requires a copy of /usr/ports
to be populated. You can use portsnap
for this. Once the /usr/ports
is populated, you can build from the <vessel>/port
directory with the standard sudo make install
or sudo make pkg
.
Initialize your user environment to work with vessel. The init command will create a minimal image by downloading the base tarball of the currently running container and installing it into a dedicated dataset. By default, vessel uses zroot
as the pool for containers. To change the pool, you can set the VESSEL_POOL
environment variable.
sudo -E vessel init
Run a shell in an ephemeral container using the previously created minimal image:
sudo -E vessel run --interactive --rm minimal:12.3-RELEASE -- sh
While quickly running a minimal container can be useful, it's generally more useful to create a customized container. For this, we can use a VesselFile which is similar to a DockerFile. Let's look at a VesselFile that creates a container to run a custom django application. Note that the modeline is set to tcl to allow for syntax highlighting
# -*- mode: tcl; indent-tabs-mode: nil; tab-width: 4; -*-
FROM FreeBSD:12.2-RELEASE
RUN mkdir -p /usr/local/etc/pkg/repos
COPY ./deployment/FreeBSD.conf /usr/local/etc/pkg/repos/FreeBSD.conf
RUN env ASSUME_ALWAYS_YES=yes pkg update -f
RUN env ASSUME_ALWAYS_YES=yes pkg install python
RUN env ASSUME_ALWAYS_YES=yes pkg install py37-django-extensions \
py37-pandas uwsgi gnuplot-lite mime-support \
py37-django-bootstrap4 py37-Jinja2 py37-psycopg2 \
nginx
RUN sysrc syslogd_enable=YES
RUN sysrc uwsgi_enable=YES
RUN sysrc uwsgi_configfile=/re/freebsd/uwsgi.ini
RUN sysrc zfs_enable=YES
RUN sysrc nginx_enable=YES
RUN sysrc clear_tmp_enable=YES
# We need to enable this kernel module via ansible first
# RUN sysrc nginx_http_accept_enable=YES
RUN sh -c "touch /var/log/all.log && chmod 600 /var/log/all.log"
RUN mkdir -p /var/log/nginx
COPY ./freebsd/syslog.conf /etc
COPY ./freebsd/nginx.conf /usr/local/etc/nginx
COPY . /re
To build the above image run:
sudo -E vessel build --file=./DjangoAppVesselFile --tag=1.0 --name=djangoapp
Once the image is built, it can be run with:
sudo -E vessel run --rm djangoapp:1.0 -- sh /etc/rc
This will start the init process in a new container running in the foreground.
The current version of vessel uses ipv4 inherited networking (IOW, the host network stack). In the future a bridged and vlan networking system with VNET will be implemented. For now, only inherited networking is used.
ℹ️ We have found that using inherited networking is not the major limitation that it seems. While a vnet based network would/could have it's uses, inherited network has met the majority of our use cases.