gnu-on-alpine and alpine-plus-plus: Two Lightweight Containers for Implementing GitHub Container Actions with Shell Scripting
Tags: github, docker, linux, devops
Published: 2023-02-21 20:38:06

## Introduction

The motivation of the [gnu-on-alpine](https://github.com/cicirello/gnu-on-alpine) and [alpine-plus-plus](https://github.com/cicirello/alpine-plus-plus) Docker containers is the implementation of [GitHub Container Actions](https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action) via shell scripting. They are built upon [alpine](https://hub.docker.com/_/alpine) to keep the image size small for fast loading within GitHub Actions, and both are preinstalled with bash, coreutils, findutils, and gawk; and alpine-plus-plus is additionally preinstalled with git.

Both gnu-on-alpine and alpine-plus-plus are multiplatform images supporting the following platforms:
* linux/386
* linux/amd64
* linux/arm/v6
* linux/arm/v7
* linux/arm64
* linux/ppc64le
* linux/s390x

__Table of Contents:__
* [Introduction](#introduction)
* [Motivation](#motivation)
* [Docker Tags and Versioning Scheme](#docker-tags-and-versioning-scheme)
* [Installing](#installing)
  * [Docker Pull Command](#docker-pull-command)
  * [Use as a base image in a Dockerfile](#use-as-a-base-image-in-a-dockerfile)
* [Learn More](#learn-more)
* [Where You Can Find Me](#where-you-can-find-me)

## Motivation

GitHub Actions can be implemented in a couple ways. The most common is with JavaScript. However, another way to implement a GitHub Action is as a [container action](https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action). As a container action, you can use any language to implement the action, provided the container includes all of the tools that your action requires. 

One simple approach is to use your favorite Linux distribution as the base image for your container, and to define the steps to install any tools that your action needs (e.g., compilers, interpreters, CLI tools, etc) within the Dockerfile of your action. The problem with that approach is that whenever a workflow of one of your users runs, the container for your action is built, which in this case includes installing the various tools that it needs.

A better approach that speeds up runs of your action is to use a base image that includes all of the tools that your action requires. This way, your Dockerfile only requires the steps necessary to copy the source of your action into the container and to set an entrypoint. Here is an example of the [Dockerfile of one of my GitHub Actions](https://github.com/cicirello/javadoc-cleanup/blob/master/Dockerfile) (note this one doesn't use the containers that are the subject of this post):

```Dockerfile
FROM ghcr.io/cicirello/pyaction:4.16.0
COPY tidyjavadocs.py /tidyjavadocs.py
ENTRYPOINT ["/tidyjavadocs.py"]
```

## Docker Tags and Versioning Scheme

I push images to both Docker Hub and the GitHub Container Registry with the following tags:
* The tag `latest` indicates, well, the latest image.
* Tags of the form MAJOR.MINOR.PATCH (such as 3.17.2) indicate the [Semantic Version](https://semver.org/) of the Alpine image used as the base.
* Tags of the form MAJOR.MINOR (e.g., 3.17) correspond to the most recent patch level of the Alpine image used as the base. For example, if 3.17.2 is the latest release, then 3.17 maps to this as well.
* Tags of the form MAJOR (e.g., 3) correspond to the most recent patch level of the Alpine image used as the base, with major corresponding major version. For example, if 3.17.2 is the latest release, then 3 maps to this as well.

I use [GitHub's dependabot](https://github.com/dependabot) to monitor for updates to the base Alpine image.


## Installing

The pre-built images are hosted on both Docker Hub and the GitHub Container Registry. You can use it in the following ways.

### Docker Pull Command

Pull the latest images from Docker Hub with the following (or replace with tag of desired version):

```Shell
docker pull cicirello/gnu-on-alpine:3.17.2
```

Or for alpine-plus-plus:

```Shell
docker pull cicirello/alpine-plus-plus:3.17.2
```

Pull from the Github Container Registry with:

```Shell
docker pull ghcr.io/cicirello/gnu-on-alpine:3.17.2
```

Or for alpine-plus-plus:

```Shell
docker pull ghcr.io/cicirello/alpine-plus-plus:3.17.2
```

### Use as a base image in a Dockerfile

Use as a base image in a Dockerfile (or replace with tag of desired version):

```Dockerfile
FROM cicirello/gnu-on-alpine:3.17.2

# The rest of your Dockerfile would go here.
```

Or for alpine-plus-plus:

```Dockerfile
FROM cicirello/alpine-plus-plus:3.17.2

# The rest of your Dockerfile would go here.
```

Or you can use as a base image (via the Github Container Registry) with:

```Dockerfile
FROM ghcr.io/cicirello/gnu-on-alpine:3.17.2

# The rest of your Dockerfile would go here.
```

Or for alpine-plus-plus:

```Dockerfile
FROM ghcr.io/cicirello/alpine-plus-plus:3.17.2

# The rest of your Dockerfile would go here.
```

## Learn More

To learn more, consult the GitHub repositories:

{% github cicirello/gnu-on-alpine %}

{% github cicirello/alpine-plus-plus %}


## Where You Can Find Me

Follow me here on DEV:

{% user cicirello %}

Follow me on GitHub:

{% github cicirello/cicirello %}

Or visit my website:

{% embed https://www.cicirello.org/ %}