Public Repository

Last pushed: 6 days ago
Short Description
EPICS base image used by DMSC Instrument Data Group.
Full Description

EPICS Base Image

EPICS is the Experimental Physics and Industrial Control System.

This image contains source and build of "EPICS base" version R3.14.12.5, the core EPICS software.

The purpose of this image is to provide a bare-bones, minimalistic EPICS base for other images to build upon.

This image itself is based on Alpine, to minimize image size and overhead.

Resources:

Image Layout

Location Contents
/EPICS/base/ EPICS base source and build
/etc/profile.d/01-epics-base.sh Sets up environment variables for serving EPICS CA (link)
/sbin/tini and /init.sh Minimalistic init system, which is described in a section below.

Usage

This image is intended to be used as a base image. To to extend it, create a new Dockerfile and reference it using the FROM directive.

To make use of the provided init system, you should keep the provided ENTRYPOINT or ensure you use /init.sh as the first field when defining your own ENTRYPOINT.

We recommend setting up any required environment variables by providing an /etc/profile.d/*.sh script and following the XY-some-name.sh naming convention, where XY is a two-digit number. Since the scripts are sourced in alphabetical order, that number can be used to control execution order.

Example Dockerfile:

FROM dmscid/epics-base:latest

RUN apk --no-cache add python

COPY 10-setup-environment.sh /etc/profile.d/10-setup-environment.sh

ENTRYPOINT ["/init.sh", "python"]

This will create an image that drops straight into a python shell, with the environment already set up by sourcing /etc/profile, /etc/profile.d/01-epics-base.sh and /etc/profile.d/10-setup-environment.sh in that order.

For a real-world example, see dmscid/epics-gateway.

Init System

Docker containers lack an init or supervisor system by default. This leads to issues with rampant root zombie processes and signals sent to the container not being passed through as expected.

These issues are described in detail here and here.

Additionally, since...

  1. The ENV directive in Dockerfiles does not currently support variable values
  2. /etc/profile and ~/.profile will not be sourced unless you explictly start a login shell
  3. /etc/bash.bashrc and ~/.bashrc will not be sourced unless you run bash in interactive but not login mode

... it can be tricky to reliably ensure environment variables are correctly set up with values that must be determined at runtime (such as a variable IP or hostname).

To resolve these issues, this image provides a combination of tini and an /init.sh script. Tini is a tiny init system that solves the zombie and signal issues. The init.sh script sources /etc/profile and ensures tini is launched correctly. This script is used as the ENTRYPOINT of this image, and derived images are encouraged to follow suit.

The script has the following usage:

. /init.sh [command [arguments]]

This will do the following:

  • /etc/profile is sourced to set up the environment (which in turn sources /etc/profile.d/*.sh)
  • [command] is run with [arguments], via tini (/sbin/tini -s -g)
  • If no command was provided, /bin/sh is used as a default
  • Assuming the script is run as the ENTRYPOINT or CMD, or by a shell that is PID 1, tini will have PID 1 so that it will receive any signals the container receives from the host
  • tini will reap child processes so they don't turn into zombies and forward any signals it receives to all child processes

The init script (or any ENTRYPOINT) may be circumvented using the --entrypoint argument of docker run. When running a container like that, you can switch to "init mode" by sourcing init.sh:

$ docker run -it --entrypoint sh dmscid/epics-base
/ # ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 sh
    7 root       0:00 ps aux
/ # . /init.sh
ac28333e09e1:/# ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 /sbin/tini -s -g -- /bin/sh
   11 root       0:00 /bin/sh
   12 root       0:00 ps aux
ac28333e09e1:/# exit
$

Note that /sbin/tini has replaced sh as the PID 1 process, and you are now in a new shell (which defaulted to /bin/sh because no parameters were passed to /init.sh). Nevertheless, a single exit shuts down the container since the old shell is gone and tini shuts down when its child process does.

Docker Pull Command
Owner
dmscid

Comments (0)