arrow-left

Only this pageAll pages
gitbookPowered by GitBook
1 of 33

Docker

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Base Images

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Applications

Loading...

Loading...

Loading...

Home

Welcome to the bfren Docker ecosystem

This started out as a project to learn Docker and have control over the versions of the various pieces of FOSS I use. But I hope you find the ecosystem as useful as I do!

The instructions assume a working knowledge of shell programming, Docker, and Docker Compose. Like most documentation they are also a work in progress...

hashtag
Licence

MITarrow-up-right (unless otherwise stated). Copyright (c) 2020-2022 bfren (unless otherwise stated).

Alpine

The base image for the bfren ecosystem, containing Alpine Linux and various helper executables.

Source filesarrow-up-right (GitHub) Container imagesarrow-up-right (Docker Hub)

hashtag
Acknowledgements

Docker Alpinearrow-up-right is a tiny distribution of Linux designed specifically for use in containers.

esharrow-up-right is a lightweight templating engine using POSIX-compatible syntax.

hashtag
Tags

x.x and x.x.x refer to the bfren image versions.

Alpine Version
Tags

In addition, you can add -dev and -beta suffixes to access development / test builds (see Docker Hub for further details).

hashtag
Environment Variables

Name
Values
Description
Default

hashtag
Packages

If you need to build the image with a different timezone to the default ("Europe/London"), you can do so by setting the TZ ARG, or by installing the tzdata package. (Please note this is only possible if you are building the image yourself - otherwise you will need to use .)

As well as the standard repositories, the edge repos are tagged with @edgemain and @edgecomm. This means you can, for example, do apk add curl@edgemain or apk add php8@edgecomm to add the edge versions of packages.

hashtag
Cron

This image contains only one service: cron, which is enabled by default. If you want to add scripts or executables to the cron you have two options.

hashtag
Option 1: /etc/periodic/

The simplest way to add tasks to the cron in Alpine Linux is to place an executable file in one of the directories under /etc/periodic/ (remember to set the executable attribute in /etc/fix-attrs.d/):

It's pretty obvious how frequently they run! An example of this method can be found in the image.

hashtag
Option 2: /etc/crontabs/root

If you want more control over your cron tasks you can create a normal crontab file:

However, if you do this, remember you will be overriding the default file when your /overlay/ is copied over the image files, so you need to include the if you don't want to break the cron further down the line.

hashtag
Templating with esh

The image comes pre-installed with , a simple shell-based templating engine. It is extremely lightweight, and very easy to use.

All dynamic configuration files in the bfren ecosystem are built using esh, and the default location for those templates is /etc/bf/templates.

3.12

alpine3.12, alpine3.12.9, alpine3.12-x.x, alpine3.12-x.x.x

3.13

alpine3.13, alpine3.13.7, alpine 3.13-x.x, alpine3.13-x.x.x

3.14

alpine3.14, alpine3.14.3, alpine3.14-x.x, alpine3.14-x.x.x

3.15

latest, alpine3, alpine3.15, alpine3.15.0, alpine3.15-x.x, alpine3.15-x.x.x

edge

alpineedge, alpineedge-x.x, alpineedge-x.x.x

BF_DEBUG

0 or 1

Set to 0 to disable debug log output messages.

1

bf-tz
Nginx PHP
default directivesarrow-up-right
esharrow-up-right
$ ls /etc/periodic/
1min    15min    daily    hourly    monthly    weekly
$ head -n 1 /etc/crontabs/root
0 */8 * * * db-backup > /dev/null 2>&1

ClamAV

ClamAV set up to run in daemon mode over the default port (3310).

Debian: Executables

Various helper executables for providing standard output and simplifying common tasks.

See Alpine: Executables.

Nginx: Helpers

Nginx PHP

Nginx base image with PHP (7.3, 7.4, and 8.0).

MariaDB

Latest stable releases of MariaDB with automated backups.

Nginx PHP: Executables

Nginx WebDAV

Nginx base image with WebDAV extensions.

PostgreSQL

Latest stable releases of PostgreSQL with automated backups.

MariaDB: Executables

Nginx

Super lightweight Nginx image with various helper configuration files.

Nginx Proxy

Automated proxy server using Nginx base image and the getssl script.

Debian S6

Another base image for the bfren ecosystem, containing Debian installed with the S6 Overlay.

Source filesarrow-up-right (GitHub) Container imagesarrow-up-right (Docker Hub)

hashtag
Acknowledgements

The S6 Overlayarrow-up-right is a version of the S6 supervisor which has various useful features for containers and managing services.

hashtag
Environment Variables, Packages, Layout

See .

Alpine S6

Redis

Latest redis cache server running in daemon mode over the default port (6379).

Debian S6: Executables

Various helper executables for interacting with S6 and the container environment.

See Alpine S6: Executables.

WordPress

Ready-to-go WordPress helpdesk with all PHP dependencies.

FreeScout

Ready-to-go FreeScout helpdesk with all PHP dependencies.

FreshRSS

Ready-to-go FreshRSS news reader with all PHP dependencies.

Nginx Proxy: Executables

FTPS

Very Secure FTP (vsftpd) supporting TLS file transfer.

Nginx: Executables

PHP

PHP installed by itself to be used in CLI mode.

PostgreSQL: Executables

ASP.NET: Executables

Various helper executables for interacting with your .NET application.

hashtag
Helpers

hashtag
aspnet-restart

Restarts ASP.NET application.

hashtag
Usage

hashtag
aspnet-start

Starts ASP.NET application.

circle-exclamation

If you try to start an application that is already running you will get an error as it won't be able to bind to port 5000. You should never need to use this executable as it is called when the container starts.

hashtag
Usage

hashtag
aspnet-switch-terminate

Stops ASP.NET application, switches live and published code, and terminates the container (you will need to have the restart policy set to 'always').

hashtag
Usage

hashtag
healthcheck

Uses to request the URL set by ASPNETCORE_URLS and exits with code 0 if response is HTTP 200 OK.

hashtag
Usage

Debian

The base image for the bfren ecosystem, containing Alpine Linux and various helper executables.

Source filesarrow-up-right (GitHub) Container imagesarrow-up-right (Docker Hub)

hashtag
Acknowledgements

Debian Slimarrow-up-right is a cut-down distribution of Debianarrow-up-right designed specifically for use in containers.

esharrow-up-right is a lightweight templating engine using POSIX-compatible syntax.

hashtag
Tags

x.x and x.x.x refer to the bfren image versions.

Debian Version
Tags

In addition, you can add -dev and -beta suffixes to access development / test builds (see Docker Hub for further details).

hashtag
Environment Variables, Packages, Cron & Templating

See .

10 (buster)

debian10, debian10-x, debian10-x.x, debian10-x.x.x

11 (bullseye)

debian11, debian11-x, debian11-x.x, debian11-x.x.x

12 (bookworm)

debian12, debian12-x, debian12-x.x, debian12-x.x.x

sid

debiansid, debiansid-x, debiansid-x.x, debiansid-x.x.x

Alpine
bf-test-url
$ aspnet-restart
[bf] 2021-09-19 18:00:00 | restart: Restarting application.
[bf] 2021-09-19 18:00:00 | bf-svc: Restarting service 'aspnet'.
$ aspnet-start
[bf] 2021-09-19 18:00:00 | start: Starting ASP.NET application.
[bf] 2021-09-19 18:00:00 | start:  .. /app/live/ASPNET_ASSEMBLY.
$ aspnet-switch-terminate
[bf] 2021-09-19 18:00:00 | bf-svc: Disabling service 'aspnet'.
[bf] 2021-09-19 18:00:00 | switch: Switching code...
[bf] 2021-09-19 18:00:00 | switch:  .. moving live files to src.OCPFfa
[bf] 2021-09-19 18:00:00 | switch:  .. moving published files to /app/live
[bf] 2021-09-19 18:00:00 | switch:  .. moving live files to /app/publish
[bf] 2021-09-19 18:00:00 | switch: done.
[bf] 2021-09-19 18:00:00 | bf-env: BF_TERMINATING=1.
[bf] 2021-09-19 18:00:00 | bf-svc-terminate: Terminating all services.
$ healthcheck
[bf] 2021-09-19 18:00:00 | healthcheck: Loading http://localhost:5000. (bf-test-url)
Connecting to localhost:5000 (127.0.0.1:5000)
remote file exists

Apache PHP

Base Apache + PHP image with MySQL enabled.

Source filesarrow-up-right (GitHub) Container imagesarrow-up-right (Docker Hub)

hashtag
Acknowledgements

Based on the official PHP imagearrow-up-right for PHP 5.6.40 with Apache and mysql extension installed.

hashtag
Ports

Port
Description

hashtag
Volumes

Volume
Purpose

80

Serves HTTP content (Apache requires permissions for user 1000, e.g. www-data).

/var/www/html/

From base image: files are served from this directory.

ASP.NET

.NET and ASP.NET runtimes pre-installed (versions 3.1, 5.0, and 6.0).

Source filesarrow-up-right (GitHub) Container imagesarrow-up-right (Docker Hub)

hashtag
Acknowledgements

Comes pre-installed with the ASP.NET runtimearrow-up-right and all required dependencies.

hashtag
Tags

.NET Version
Tags

In addition, you can add -dev and -beta suffixes to access development / test builds (see Docker Hub for further details).

hashtag
Ports

Port
Description

hashtag
Volumes

Volume
Purpose

hashtag
Environment Variables

Name
Values
Description
Default

Alpine S6

The base image for much of the bfren ecosystem, containing Alpine Linux installed with the S6 Overlay.

(GitHub) (Docker Hub)

hashtag
Acknowledgements

The is a version of the S6 supervisor which has various useful features for containers and managing services.

Alpine S6: Executables

Various helper executables for interacting with S6 and the container environment.

hashtag
Output

hashtag
bf-svc-finish

Outputs service closing down debug message and optionally terminates all running services. Usually used in /etc/services.d/xxx/finish file to show

hashtag
Arguments

  • -s X outputs a message that service "X" is shutting down

  • -t terminates all other services as well

hashtag
Usage

hashtag
Helpers

hashtag
bf-clear-src

Clears contents of /etc/bf/src.

hashtag
Usage

hashtag
bf-cron

Run all scripts within a cron directory.

hashtag
Arguments

  • -h Show usage

  • -q Run quietly (otherwise it will output that the cron is being run to the logs - individual scripts may still send output)

  • DIRECTORY - the directory within /etc/periodic to run

hashtag
Usage

hashtag
bf-env

Adds a container environment variable called $1 with value $2.

hashtag
Arguments

  1. Variable name

  2. Variable value

hashtag
Usage

hashtag
bf-fix-attrs

Re-applies attributes and permissions defined in /etc/fix-attrs.d. Based on code from S6 Overlayarrow-up-right.

hashtag
Usage

hashtag
bf-forward

Forwards errors logged in $2 to Docker logs; if $2 is not set, disables service $1.

hashtag
Arguments

  1. Service name.

  2. Absolute path to log file.

hashtag
Usage

hashtag
bf-svc

Uses S6 to control the service named $2.

hashtag
Arguments

  1. Control action: 'disable', 'restart', 'start', 'stop'

  2. Service name

hashtag
Usage

hashtag
bf-svc-terminate

Terminates all running services - usually used in /etc/services.d/xxx/finish file - which also closes down (and potentially restarts) the whole container.

hashtag
Usage

$ bf-svc-finish -s cron
[bf] 2021-09-23 10:21:52 | cron/finish: Service closing down.

$ bf-svc-finish -s cron -t
[bf] 2021-09-19 18:00:00 | cron/finish: Service closing down.
[bf] 2021-09-19 18:00:00 | bf-env: BF_TERMINATING=1.
[bf] 2021-09-19 18:00:00 | bf-svc-terminate: Terminating all services.
[bf] 2021-09-19 18:00:00 | cron-log/finish: Service closing down.
[cont-finish.d] executing container finish scripts...
[cont-finish.d] 00-clear: executing...
[bf] 2021-09-19 18:00:00 | 00-clear: Clearing /tmp... (bf-clear)
[bf] 2021-09-19 18:00:00 | 00-clear: done. (bf-clear)
[bf] 2021-09-19 18:00:00 | 00-clear: Clearing caches... (bf-clear)
[bf] 2021-09-19 18:00:00 | 00-clear: done. (bf-clear)
[cont-finish.d] 00-clear: exited 0.
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.
$ bf-clear-src
[bf] 2021-09-19 18:00:00 | bf-clear-src: Clearing /etc/bf/src...
[bf] 2021-09-19 18:00:00 | bf-clear-src: done.
$ bf-cron 1min
[bf] 2021-09-19 18:00:00 | bf-cron: /etc/periodic/1min.

$ bf-cron -q 1min
// scripts are run with no output
$ bf-env "DOCS" "Docker Docs"
[bf] 2021-09-19 18:00:00 | bf-env: DOCS=Docker Docs.
$ bf-fix-attrs
[bf] 2021-09-19 18:00:00 | bf-fixattrs: Applying ownership & permissions fixes...
[bf] 2021-09-19 18:00:00 | bf-fixattrs: 00-alpine-s6: applying...
[bf] 2021-09-19 18:00:00 | bf-fixattrs: 00-alpine-s6: exited 0.
[bf] 2021-09-19 18:00:00 | bf-fixattrs: done.
$ bf-forward cron-log /var/log/cron.log
[bf] 2021-09-19 18:00:00 | [bf] 2021-09-23 09:57:59 | cron-log/run: Forwarding cron-log - /var/log/cron.log. (bf-forward)
$ bf-svc restart cron
[bf] 2021-09-19 18:00:00 | bf-svc: Restarting service 'cron'.
[bf] 2021-09-19 18:00:00 | cron/finish: Service closing down.
[bf] 2021-09-19 18:00:00 | cron/run: Starting cron.
crond: crond (busybox 1.33.1) started, log level 8
$ bf-svc-terminate
[bf] 2021-09-19 18:00:00 | bf-env: BF_TERMINATING=1.
[bf] 2021-09-19 18:00:00 | bf-svc-terminate: Terminating all services.
[bf] 2021-09-19 18:00:00 | cron/finish: Service closing down.
[bf] 2021-09-19 18:00:00 | cron-log/finish: Service closing down.
[cont-finish.d] executing container finish scripts...
[cont-finish.d] 00-clear: executing...
[bf] 2021-09-19 18:00:00 | 00-clear: Clearing /tmp... (bf-clear)
[bf] 2021-09-19 18:00:00 | 00-clear: done. (bf-clear)
[bf] 2021-09-19 18:00:00 | 00-clear: Clearing caches... (bf-clear)
[bf] 2021-09-19 18:00:00 | 00-clear: done. (bf-clear)
[cont-finish.d] 00-clear: exited 0.
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.

This should always be set to true - it tells dotnet that it is running in a container environment.

'true'

DOTNET_SYSTEM_GLOBALIZATION_INVARIANT

'true' or 'false'

See and .

'true'

3.1

net3, net3.1, net3.1.21

5.0

net5, net5.0, net5.0.12

6.0

latest, net6, net6.0, net6.0.0

5000

Serves HTTP content from your application.

/app/live

Contains live application files.

/app/publish

Publish updated files to this directory and use aspnet-switch-terminate to make it go live.

ASPNET_ASSEMBLY

string

The filename of the assembly to execute.

None - required

ASPNETCORE_URLS

string

Default value binds web server to port 5000 - should not normally need to be changed.

http://+:5000arrow-up-right

DOTNET_RUNNING_IN_CONTAINER

'true' or 'false'

hashtag
Environment Variables
Name
Values
Description
Default

BF_CRON_LOG_LEVEL

0-8

Cron log level (0 is most verbose).

8

hashtag
Packages

The image comes with the S6 Overlay and all its dependencies.

hashtag
Layout

The most important concept in these images is the /overlay/ directory, which is copied from the source over the top of the image. You can use whatever structure you like within that.

So, for example, the edge repositories are added via the /overlay/etc/apk/repositories file, which is copied over the top of the base image filesystem by the Dockerfile command COPY ./overlay /.

You can add any files you want to the image this way.

hashtag
S6 Startup

Every time the container starts, the S6 Overlay runs the same series of scripts. These allow you to ensure that there is a consistent environment for your service.

The sequence is as follows (all should be contained within the /overlay/ directory):

  1. /etc/fix-attrs.d/ - set required permissions

  2. /etc/cont-init.d/ - run initialisation scripts

  3. /etc/services.d/ - register the services you want to be supervised

circle-info

My rule of thumb is that the first image uses 0-based files. Then the next uses 1-based files, then 2-based, etc. As S6 loads these files alphabetically, this practice ensures base permissions and configuration is always done first.

The S6 Overlay does more before and after all this - additional information can be found in their documentationarrow-up-right. These three folders are where you will most often hook into the container processes.

hashtag
Permissions

For me, permissions are one the most powerful and most frustrating features of Linux. These are set by adding files to /overlay/etc/fix-attrs.d/. Good practice is to prefix these files with a number so you have control over the order in which they are loaded. For example:

  • First we have the absolute path to the file or directory to set permissions for

  • Next we have true or false whether or not to recurse (obviously meaningless for a file)

  • Then we have the owner of the file or directory

  • Finally we have the permissions, first fmode (file permissions) and then dmode (directory permissions). I find the extremely useful for generating these.

You can have as many of these as you wish, and you can reapply them at any point by using bf-fix-attrs.

hashtag
Initialisation

After the permissions are set, the scripts in /etc/cont-init.d/ are run. Here you might want to run installation routines, create configuration files, etc.

For example, in the ClamAV image the following two scripts run in this stage:/etc/cont-init.d/10-initial # downloads the latest virus definitions

Notice that in this example the files begin 10- and 11- as mentioned earlier.

(It does mean there can't be more than ten initialisation scripts per image, but frankly if there are more we need to ask the question, is the image trying to do too much? A key principle of Docker is that an image should do one thing.)

hashtag
Services

All the services you want to be managed by S6 go in /etc/services.d/. The name of the next directory will be the name of the service, e.g. cron. Within that the minimum you need is a file named run, which contains the script necessary to start your service.

Here is the run file from the cron service of this image:

As you can see, it doesn't have to be complex! The trick with this particular example is the -f flag which tells the cron daemon to run in the foreground. If it ran in the background, S6 wouldn't be able to supervise it. This is something to watch out for when creating your own services.

You can have as many services as you want - however the main point of Docker is to separate services into their own 'contained' environments. Therefore I try to keep the discipline of one 'main' service, and only adding 'supporting' services beyond that.

So, for example, in the Nginx image, the main service is nginx itself, but there are also two services to manage logging.

Note that service directories are not given a number prefix - they will run in any order. S6 does have ways of making a service wait for another service to start, but it's complex and very fiddly. Plus, if something needs to happen before your service starts, it should probably go in /etc/cont-init.d/ instead.

In your main service directory, I suggest also including a finish file:

This is also from the cron service of this image, but you'll see it in the main service directory of all the bfren images. What this does is tell S6 to close down all the services gracefully when this one quits, and then stop the container. You don't have to do this, but it's good practice to ensure a safe closedown of your container services when one of them crashes.

It means you may want to set restart to unless-stopped instead of always, or you could end up with a never-ending loop of a container starting, crashing, restarting, crashing, etc.

hashtag
Container Environment

One of the most useful tricks when using S6 is to make use of the following directive to import all environment variables into the current script:

This is an example from the ClamAV image (in fact it is the contents of the 11-updater file we looked at earlier). One of that image's environment variables is FRESHCLAM_PER_DAY which allows you to define how many times a day you want freshclam to run.

You do not get Docker's environment variables in scripts by default however, so you need to use the S6 helper function with-contenv (with container environment). Then you can access all the environment variables you want.

hashtag
Have fun!

And that's it! There is a lot more to it if you want to get complicated - I suggest you read the S6 documentation if you want to go deeper..

Source filesarrow-up-right
Container imagesarrow-up-right
S6 Overlayarrow-up-right
# fix-attrs.d/00-bin
/usr/local/bin/healthcheck false root:root 0500 0500

# fix-attrs.d/01-user
/etc/user true www:www 0644 0755
/etc/cont-inid.d/11-updater # registers the freshclam update daemon
#!/bin/sh
/usr/sbin/crond -f
#!/bin/sh
s6-svscanctl -t /var/run/s6/services
#!/usr/bin/with-contenv sh
freshclam -d -c ${FRESHCLAM_PER_DAY}
chmod calculatorarrow-up-right
herearrow-up-right
herearrow-up-right

Alpine: Executables

Various helper executables for providing standard output and simplifying common tasks.

hashtag
Output

hashtag
bf-debug

Echoes "$1: $2" to stdout in grey with prefix (see ) - but only if BF_DEBUG is set to "1".

hashtag
Arguments

  1. Text to output

  2. [Optional] Script / executable name

hashtag
Usage

hashtag
bf-done

Echoes 'done.' to stdout in green with prefix (see ).

hashtag
Arguments

  1. [Optional] Script / executable name

hashtag
Usage

hashtag
bf-e

Echoes $3 to stdout in colour $2 with prefix: "[$1] %Y-%m-%d %H:%M:%S".

hashtag
Arguments

  1. Namespace (default value for other output helper executables is 'bf')

  2. ANSI colour code (see e.g. )

  3. Text to output

hashtag
Usage

hashtag
bf-echo

Echoes "$1: $2" to stdout in default colour with prefix (see ).

hashtag
Arguments

  1. Text to output

  2. [Optional] Script / executable name

hashtag
Usage

hashtag
bf-error

Echoes "$1: $2" to stdout in red with prefix (see ), and returns 1. This will end execution of the calling script if you use, e.g. set -euo pipefail at the top of your scripts (recommended).

hashtag
Arguments

  1. Text to output

  2. [Optional] Script / executable name

hashtag
Usage

hashtag
bf-notok

Like echoes "$1: $2" to stdout in red with prefix, but doesn't end execution of calling script.

hashtag
Arguments

  1. Text to output

  2. [Optional] Script / executable name

hashtag
Usage

hashtag
bf-ok

Echoes "$1: $2" to stdout in green with prefix.

hashtag
Arguments

  1. Text to output

  2. [Optional] Script / executable name

hashtag
Usage

hashtag
Helpers

hashtag
bf-adduser

Create user with id $2, group with id $3, both with name $1, and no password.

hashtag
Arguments

  1. User and group name

  2. [Optional] User ID (default: 1000)

  3. [Optional] Group ID (default: UID)

hashtag
Usage

hashtag
bf-ch

Changes ownership and/or permissions of file / directory glob.

hashtag
Arguments

Required (one or both):

  • -o X use chown to set ownership to "X"

  • -m Y use chmod to set permissions to "Y"

Optional:

  • -t f|d apply only to files ("f") or directories ("d")

  • -rif -t is not specified, applies action recursively to all files and directories

hashtag
Usage

hashtag
bf-clear

Clears contents of /tmp and apk cache.

hashtag
Usage

hashtag
bf-esh

Calls esh in a consistent manner.

hashtag
Arguments

  1. Path to input (template) file

  2. Path to output (generated) file

hashtag
Usage

hashtag
bf-image

Display name and version of the current image, and a link to the GitHub repository.

hashtag
Usage

hashtag
bf-install

Run install /tmp/install and then perform cleanup (see ). Within the ecosystem this would normally be used in a Dockerfile

hashtag
Usage

This is the basic structure of Dockerfiles based on the Alpine S6 image, copying overlay and then running the standard installation.

hashtag
bf-rmrf

Runs rm -rf $1 safely: doing nothing if $1 is empty. This is handy if the path you are deleting is contained in a variable (it effectively stops rm -rf /!).

hashtag
Arguments

  1. Folder path / file glob to delete.

hashtag
Usage

hashtag
bf-rnd

Generates a string of random letters and numbers of length $1.

hashtag
Arguments

  1. [Optional] Number of characters to return

hashtag
Usage

hashtag
bf-test-url

Uses wget to test URL $1.

hashtag
Arguments

  1. URL to test

hashtag
Usage

hashtag
bf-tz

Sets the container's timezone to $1. (Installs tzdata package, changes timezone and then removes tzdata).

hashtag
Arguments

  1. Valid timezone (e.g. Europe/London)

hashtag
Usage

Note the change in time on line 12.

[Optional] Script / executable name
bf-e
environment variable
bf-ok
herearrow-up-right
bf-e
bf-e
bf-error
bf-clear
$ bf-debug "Hi"
[bf] 2021-09-19 18:00:00 | Hi # (in grey)

$ bf-debug "Hi" "alpine-s6/docs"
[bf] 2021-09-19 18:00:00 | alpine-s6/docs: Hi # (in grey)
$ bf-done
[bf] 2021-09-19 18:00:00 | done. # (in green)

$ bf-done "alpine-s6/docs"
[bf] 2021-09-19 18:00:00 | alpine-s6/docs: done. # (in green)
$ bf-e "docs" "\e[91m" "Hi"
[docs] 2021-09-19 18:00:00 | Hi # (in red)

$ bf-e "docs" "\e[92m" "Hi" "alpine-s6"
[docs] 2021-09-19 18:00:00 | alpine-s6: Hi # (in green)
$ bf-echo "Hi"
[bf] 2021-09-19 18:00:00 | Hi # (in black / white)

$ bf-echo "Hi" "docs"
[bf] 2021-09-19 18:00:00 | docs: Hi # (in black / white)
$ bf-error "Die"
[bf] 2021-09-19 18:00:00 | Die # (in red)

$ bf-error "Die" "docs"
[bf] 2021-09-19 18:00:00 | docs: Die # (in red)
$ bf-notok "Error"
[bf] 2021-09-19 18:00:00 | Error # (in red)

$ bf-notok  "Error" "docs"
[bf] 2021-09-19 18:00:00 | docs: Error # (in red)
$ bf-ok "Hi"
[bf] 2021-09-19 18:00:00 | Hi # (in green)

$ bf-ok  "Hi" "docs"
[bf] 2021-09-19 18:00:00 | docs: Hi # (in green)
$ bf-adduser "fred"
[bf] 2021-09-19 18:00:00 | bf-adduser: Adding user and group 'fred'...
[bf] 2021-09-19 18:00:00 | bf-adduser: done. 'fred'... # (in green)
$ cat /etc/passwd
...
fred:x:1000:1000:Linux User,,,:/home/fred:/bin/ash

$ bf-adduser "fred" 1001
[bf] 2021-09-19 18:00:00 | bf-adduser: Adding user and group 'fred'...
[bf] 2021-09-19 18:00:00 | bf-adduser: done. 'fred'... # (in green)
$ cat /etc/passwd
...
fred:x:1001:1001:Linux User,,,:/home/fred:/bin/ash

$ bf-adduser "fred" 1002 1003
[bf] 2021-09-19 18:00:00 | bf-adduser: Adding user and group 'fred'...
[bf] 2021-09-19 18:00:00 | bf-adduser: done. 'fred'... # (in green)
$ cat /etc/passwd
...
fred:x:1002:1003:Linux User,,,:/home/fred:/bin/ash
$ bf-ch -o "fred" -m 777 -t f /tmp
[bf] 2021-09-19 18:00:00 | bf-ch: Applying chown fred to /tmp.
[bf] 2021-09-19 18:00:00 | bf-ch:  .. type f.
[bf] 2021-09-19 18:00:00 | bf-ch: Applying chmod 777 to /tmp.
[bf] 2021-09-19 18:00:00 | bf-ch:  .. type f.

$ bf-ch -o "fred" -m 777 -r /tmp
[bf] 2021-09-19 18:00:00 | bf-ch: Applying chown fred to /tmp.
[bf] 2021-09-19 18:00:00 | bf-ch:  .. recursively.
[bf] 2021-09-19 18:00:00 | bf-ch: Applying chmod 777 to /tmp.
[bf] 2021-09-19 18:00:00 | bf-ch:  .. recursively.
$ bf-clear
[bf] 2021-09-19 18:00:00 | bf-clear: Clearing /tmp...
[bf] 2021-09-19 18:00:00 | bf-clear: done.
[bf] 2021-09-19 18:00:00 | bf-clear: Clearing caches...
[bf] 2021-09-19 18:00:00 | bf-clear: done.
$ bf-esh /path/to/template /path/to/output
[bf] 2021-09-19 18:00:00 | bf-esh: /path/to/output created.
$ bf-image
[bf] 2021-09-19 18:00:00 | bf-image: bfren alpine 1.2.0.
[bf] 2021-09-19 18:00:00 | bf-image: https://github.com/bfren/docker-alpine.
FROM quay.io/bfren/alpine-s6:alpine3.14

COPY ./overlay /

RUN bf-install
$ bf-rmrf ""
[bf] 2021-09-19 18:00:00 | bf-rmrf: Cannot remove ''.

bf-rmrf /tmp/*
[bf] 2021-09-19 18:00:00 | bf-rmrf: Removing /tmp/*.
$ bf-rnd
7ceeezFaFzbuaHujA2ST2s3ACPAnAEoUqqVXBcdk

$ bf-rnd 10
D8ORzTX56m

$ RND=$(bf-rnd)
$ echo ${RND}
cm1HuNlkQwbqd5TeApoHsxfYE6X1MWxKnuiBbjFr
$ bf-test-url https://fake.url
[bf] 2021-09-19 18:00:00 | bf-test-url: Loading https://fake.url.
wget: bad address 'fake.url'

$ bf-test-url https://bbc.co.uk
[bf] 2021-09-19 18:00:00 | bf-test-url: Loading https://bbc.co.uk.
Connecting to bbc.co.uk (151.101.0.81:443)
Connecting to www.bbc.co.uk (212.58.237.254:443)
remote file exists
$ bf-tz UTC
[bf] 2021-09-19 18:00:00 | bf-tz: Installing tzdata packages.
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/edge/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/edge/community/x86_64/APKINDEX.tar.gz
(1/2) Installing tzdata (2021a-r0)
(2/2) Installing .tz (20210923.092854)
Executing busybox-1.33.1-r3.trigger
OK: 9 MiB in 17 packages
[bf] 2021-09-19 18:00:00 | bf-tz: Setting timezone to UTC...
[bf] 2021-09-19 17:00:00 | bf-tz: Removing tzdata packages.
(1/2) Purging .tz (20210923.092854)
(2/2) Purging tzdata (2021a-r0)
Executing busybox-1.33.1-r3.trigger
OK: 6 MiB in 15 packages
[bf] 2021-09-19 17:00:00 | bf-tz: done.

$ cat /etc/localtime
TZif2UTCTZif2UTC
UTC0