You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
428 lines
12 KiB
Markdown
428 lines
12 KiB
Markdown
# pyentrypoint
|
|
|
|
__pyentrypoint__ is a tool written in `Python` to manage Docker containers `ENTRYPOINT`.
|
|
|
|
This tool avoids writing shell scripts to:
|
|
- Handle commands and sub commands
|
|
- Identify linked containers
|
|
- Generate configuration using `jinja2` templates
|
|
- Run commands before starting service
|
|
- Reload service when configuration has changed
|
|
|
|
[![Documentation Status](https://readthedocs.org/projects/pyentrypoint/badge/?version=latest)](http://pyentrypoint.readthedocs.io/en/latest/?badge=latest) [![Build Status](https://travis-ci.org/cmehay/pyentrypoint.svg?branch=master)](https://travis-ci.org/cmehay/pyentrypoint)
|
|
|
|
|
|
## Changelog
|
|
|
|
###### v0.7.2 (2020-05-30)
|
|
- add set_environment in settings
|
|
|
|
###### v0.7.1 (2020-05-24)
|
|
- add envtobool function in configuration template
|
|
|
|
###### v0.7.0 (2020-05-17)
|
|
- Add command matching setup
|
|
|
|
###### V0.6.0 (2020-05-10)
|
|
- Drop python 2 support
|
|
- Deprecation of `command` and `subcommands` settings for `commands` (see bellow)
|
|
|
|
## Usages
|
|
|
|
### Install in container
|
|
|
|
All you need to do is to setup a `yaml` file called `entrypoint-config.yml` and to install __pyentrypoint__ in your `Dockerfile` using pip.
|
|
|
|
```dockerfile
|
|
FROM debian
|
|
# Installing git for example
|
|
RUN apt-get update && apt-get install git python-pip -y
|
|
# Install pyentrypoint
|
|
RUN pip install pyentrypoint
|
|
# Copy config file in the current WORKDIR
|
|
COPY entrypoint-config.yml .
|
|
# Set ENTRYPOINT
|
|
ENTRYPOINT ['pyentrypoint']
|
|
# git will be the default command
|
|
CMD ['git']
|
|
```
|
|
|
|
```dockerfile
|
|
FROM alpine
|
|
# Installing git for example
|
|
RUN apk add --update py-pip git
|
|
# Install pyentrypoint
|
|
RUN pip install pyentrypoint
|
|
# Copy config file in the current WORKDIR
|
|
COPY entrypoint-config.yml .
|
|
# Set ENTRYPOINT
|
|
ENTRYPOINT ['pyentrypoint']
|
|
# git will be the default command
|
|
CMD ['git']
|
|
```
|
|
|
|
#### Using docker-image
|
|
|
|
```dockerfile
|
|
FROM goldy/pyentrypoint:python3
|
|
|
|
# ONBUILD statement add entrypoint-config.yml in current directories
|
|
|
|
```
|
|
|
|
Available with many flavours:
|
|
|
|
- `goldy/pyentrypoint:python3`
|
|
- `goldy/pyentrypoint:python3.6`
|
|
- `goldy/pyentrypoint:python3.7`
|
|
- `goldy/pyentrypoint:python3.8`
|
|
- `goldy/pyentrypoint:python3-alpine`
|
|
- `goldy/pyentrypoint:python3.6-alpine`
|
|
- `goldy/pyentrypoint:python3.7-alpine`
|
|
- `goldy/pyentrypoint:python3.8-alpine`
|
|
|
|
|
|
|
|
|
|
### Working examples
|
|
- [Tor hidden service](https://github.com/cmehay/docker-tor-hidden-service)
|
|
|
|
### Setup entrypoint
|
|
|
|
This is an example of `entrypoint-config.yml` file.
|
|
|
|
```yaml
|
|
# Entrypoint configuration example
|
|
|
|
# This setup lists commands handled by entrypoint.
|
|
# If you run the container with a command not in this list,
|
|
# pyentrypoint will run the command directly without any action
|
|
# If this setting and `command` are not set, all commands will be handled.
|
|
# Support wildcard
|
|
commands:
|
|
- git
|
|
- sl*
|
|
|
|
# DEPRECATED: This setup is remplaced by `commands`
|
|
# This entry should reflect CMD in Dockerfile
|
|
# If `commands` is present, this setup will be ignored.
|
|
# DEPRECATED: This setup is remplaced by `commands`
|
|
command: git
|
|
|
|
# DEPRECATED: This setup will be dropped
|
|
# This is a list with some subcommands to handle
|
|
# when CMD is not `git` here.
|
|
# By default, all args started with hyphen are handled.
|
|
# DEPRECATED: This setup will be dropped
|
|
subcommands:
|
|
- "-*"
|
|
- clone
|
|
- init
|
|
- ls-files
|
|
# etc...
|
|
|
|
# User and group to run the cmd.
|
|
# Can be name or uid/gid.
|
|
# Affect only command handled.
|
|
# Dockerfile USER value by default.
|
|
user: 1000
|
|
group: 1000
|
|
|
|
# These files should exist (ADD, COPY or mounted)
|
|
# and should be jinja templated.
|
|
# Note: if config files end with ".tpl", the extension will be removed.
|
|
config_files:
|
|
- /etc/gitconfig
|
|
- .ssh/config.tpl # Will apply to ".ssh/config"
|
|
- /tmp/id_rsa: .ssh/id_rsa # Will apply "/tmp/id_rsa" template to ".ssh/id_rsa"
|
|
|
|
|
|
# These environment variables will be wiped before
|
|
# exec command to keep them secret
|
|
# CAUTION: if the container is linked to another one,
|
|
# theses variables will passed to it anyway
|
|
secret_env:
|
|
- SSHKEY
|
|
- '*' # Support globbing, all environment will be wiped
|
|
|
|
# Links are handled here
|
|
# Port, name, protocol or env variable can be used to identify the links
|
|
# Raise an error if the link could not be identified
|
|
# This is not supported when using docker network or docker-compose v2.
|
|
links:
|
|
'ssh':
|
|
port: 22
|
|
name: 'ssh*'
|
|
protocol: tcp
|
|
# env can be list, dictionary or string
|
|
env:
|
|
FOO: bar
|
|
# Single doesn't allow multiple links for this ID
|
|
# false by default
|
|
single: true
|
|
# Set to false to get optional link
|
|
# true by default
|
|
required: true
|
|
|
|
# Set custom environment variable by running commands
|
|
# Will run before pre_conf_commands and capture stdout only
|
|
# Stop init if crash
|
|
set_environment:
|
|
- ENV_1: echo 'The environment variable ENV_1 will be added with this phrase'
|
|
- ENV_2: head /dev/urandom | base64
|
|
- ENV_3: echo ${ENV_1} and ${ENV_2} are now available here
|
|
- ENV_4: exit 1 || true # Set like this if you need to ignore error
|
|
|
|
# Commands to run before applying configuration
|
|
pre_conf_commands:
|
|
- echo something > to_this_file
|
|
|
|
# commands to run after applying configuration
|
|
post_conf_commands:
|
|
- echo "something else" > to_this_another_file
|
|
|
|
# commands to run in parallele with the main command
|
|
post_run_commands:
|
|
- echo do something in parallele with the main command
|
|
|
|
# run post_run_commands in parallele or sequentially (default is sequential)
|
|
run_post_commands_in_parallele: true # default false
|
|
|
|
# Reload service when configuration change by sending a signal to process
|
|
reload:
|
|
signal: SIGHUP # Optional, signal to send, default is SIGHUP
|
|
pid: 1 # Optional, pid to send signal, default is 1
|
|
watch_config_files: true # Optional, watch defined config files, default True
|
|
files: # Optional, list of files to watch
|
|
- /etc/conf/to/watch
|
|
- /file/support/*.matching
|
|
# can also be enabled like this:
|
|
reload: true
|
|
|
|
|
|
# Cleanup environment from variables created by linked containers
|
|
# before running command (True by default)
|
|
clean_env: true
|
|
|
|
# Enable debug to debug
|
|
debug: true
|
|
|
|
# Do not output anything except error
|
|
quiet: false
|
|
```
|
|
|
|
#### Handled command matching
|
|
|
|
All settings can be mapped to an handled command.
|
|
|
|
For instance:
|
|
|
|
```yaml
|
|
|
|
# This config will handle command `abc` and `xyz`
|
|
commands:
|
|
- abc
|
|
- xyz
|
|
|
|
# you can map commands to handled commands bellow
|
|
pre_conf_commands:
|
|
- abc:
|
|
- echo "will run for command abc"
|
|
- xyz:
|
|
- echo "will run for command xyz"
|
|
- echo "Can be multiple"
|
|
- echo "Will run for both commands"
|
|
|
|
user:
|
|
- abc: 1000
|
|
- xyz: 1001
|
|
|
|
# Mapping can also be a dictionnary
|
|
group:
|
|
abc: 1000
|
|
xyz: 1001
|
|
|
|
# Etc
|
|
```
|
|
|
|
Not supported for deprecated settings `command`, `subcommands` and `links`.
|
|
|
|
|
|
|
|
### Config templates
|
|
|
|
You can generate configuration for your service with jinja2 template.
|
|
|
|
**`links` and `containers` are not supported with docker network and docker-compose v2.**
|
|
|
|
Here is an example for an hypothetical ssh config file:
|
|
|
|
```jinja
|
|
host server:
|
|
hostname {{links.ssh.ip}}
|
|
port {{links.ssh.port}}
|
|
```
|
|
|
|
Templates will be replaced with ip address and port of the identified link. All links can be accessed from `links.all`, this is a tuple of links you can iterate on it.
|
|
|
|
```jinja
|
|
{% for link in links.all %}
|
|
host {{link.names[0]}}
|
|
hostname {{link.ip}}
|
|
port {{links.port}}
|
|
{% endfor %}
|
|
```
|
|
|
|
If you change the option `single` to `false` in the `entrypoint-config.yml`, the identified link `ssh` will become a tuple of links. You must iterate on it in the `jinja` template.
|
|
|
|
```jinja
|
|
{% for link in links.ssh %}
|
|
host {{link.names[0]}}
|
|
hostname {{link.ip}}
|
|
port {{links.port}}
|
|
{% endfor %}
|
|
```
|
|
|
|
Accessing environment in template.
|
|
|
|
```jinja
|
|
{% if 'SSHKEY in env' %}
|
|
{{env['SSHKEY']}}
|
|
{% endfor %}
|
|
```
|
|
|
|
### Accessible objects
|
|
|
|
You have 8 available objects in your templates.
|
|
|
|
- `config`
|
|
- `links`
|
|
- `containers`
|
|
- `environ`
|
|
- [`yaml`](https://pypi.org/project/PyYAML/)
|
|
- [`json`](https://docs.python.org/fr/3/library/json.html)
|
|
- [`toml`](https://pypi.org/project/toml/)
|
|
- [`ConfigParser`](https://docs.python.org/3/library/configparser.html)
|
|
|
|
#### ConfigParser
|
|
|
|
ConfigParser has an extra `to_string` method to write config as string in jinja templace, or can be casted to sting.
|
|
|
|
`read*` methods also return self object (unlike the original methods which are retuning `None`)
|
|
|
|
```jinja
|
|
{% set config = ConfigParser().read_string(env['SOME_CONF_IN_ENVIRONMENT'])}
|
|
{# Write parsed config like this #}
|
|
{{ str(config) }}
|
|
```
|
|
|
|
#### config
|
|
|
|
`Config` reflect the config file. You can retrieve any setup in this object.
|
|
|
|
(see `config.py`)
|
|
|
|
#### links
|
|
|
|
**Not supported with docker network and docker-compose v2**
|
|
|
|
`Links` handles `Link` objects. You can identify links using wildcard patterns in the configuration file.
|
|
|
|
`link` is related to one physical link (one ip and one port).
|
|
|
|
`link` handles the following attributes:
|
|
- `ip`
|
|
- link ip
|
|
- `port`
|
|
- link port (integer)
|
|
- `environ`
|
|
- related container environment
|
|
- `protocol`
|
|
- link protocol (`tcp` or `udp`)
|
|
- `uri`
|
|
- link URI (example: `tcp://10.0.0.3:80`)
|
|
- `names`
|
|
- tuple of related container names
|
|
|
|
#### containers
|
|
|
|
**Not supported with docker network and docker-compose v2**
|
|
|
|
`containers` handles a tuple of `container` object.
|
|
|
|
`container` handles the following attributes:
|
|
- `ip`
|
|
- container ip
|
|
- `environ`
|
|
- container environment
|
|
- `names`
|
|
- List of containers names
|
|
- Names are sorted by length, but container ID will be the last element.
|
|
- `id`
|
|
- Hexadecimal container ID (if available, empty string else)
|
|
- `links`
|
|
- Tuple of `link` objects related to this container
|
|
|
|
#### environ
|
|
`environ` is the environment of the container (os.environ).
|
|
|
|
`env` is an alias to `environ`.
|
|
|
|
##### envtobool
|
|
`envtobool` function is a useful to parse boolean string input in environnement to enable or disable features.
|
|
|
|
The function accepts a default value as second parameter.
|
|
|
|
```jinja
|
|
{% if envtobool('SOME_ENV_VARIABLE', False) %}
|
|
do stuff
|
|
{% endif %}
|
|
|
|
# Will write True or False here
|
|
{envtobool('SOME_OTHER_ENV_VARIABLE', True)}
|
|
```
|
|
|
|
See https://docs.python.org/3/distutils/apiref.html#distutils.util.strtobool for information on input.
|
|
|
|
#### yaml and json
|
|
|
|
`yaml` and `json` objects are respectively an import of [`PyYAML`](http://pyyaml.org/) and [`json`](https://docs.python.org/2/library/json.html) modules.
|
|
|
|
They are useful to load and dump serialized data from environment.
|
|
|
|
```jinja
|
|
# Here yaml is present in SETUP_YAML environment variable
|
|
{% set data = yaml.load(env['SETUP_YAML'])%}
|
|
{{data['param']}}
|
|
|
|
# Here json is present in SETUP_JSON environment variable
|
|
{% set data = json.loads(env['SETUP_JSON'])%}
|
|
{{data['param']}}
|
|
```
|
|
|
|
## Setup
|
|
|
|
Some setups can be overridden using environment variables.
|
|
|
|
- `ENTRYPOINT_CONFIG` overrides path of `entrypoint-config.yml` file.
|
|
- `ENTRYPOINT_FORCE` is applying configuration and runs pre and post conf commands even if the `command` provided is not handled.
|
|
- `ENTRYPOINT_PRECONF_COMMAND` run an extra pre conf shell command after all pre conf commands.
|
|
- `ENTRYPOINT_POSTCONF_COMMAND` run an extra post conf shell command after all post conf commands.
|
|
- `ENTRYPOINT_DEBUG` enables debug logs.
|
|
- `ENTRYPOINT_RAW` does not use logging to display pre and post conf commands.
|
|
This can be useful if output is serialized.
|
|
- `ENTRYPOINT_DISABLE_RELOAD` disable reload system even if it is enabled in `entrypoint-config.yml`.
|
|
- `ENTRYPOINT_USER` overrides `user` in config.
|
|
- `ENTRYPOINT_GROUP` overrides `group` in config.
|
|
- `ENTRYPOINT_DISABLE_SERVICE` exits container with 0 before doing anything. Useful to disable container using environement.
|
|
|
|
|
|
|
|
### Running Tests
|
|
|
|
To run tests, ensure that `docker-compose` and `make` are installed and run
|
|
|
|
```shell
|
|
$ make test
|
|
```
|