# podman helper scripts

## configuration files

### podman config

Podman (as root) normally uses /etc/containers/containers.conf,
storage.conf and registries.conf for its configuration.

To allow user override scripts will also look at /etc/atmark/containers.conf,
containers_storage.conf and containers_registries.conf and ignore analogous
files in /etc/containers if they exist.

This can be useful if e.g. user wants to define their own registry, or add
different additionalimagestores (note the update script will stop working
if stores are changed)

### containers config

containers can be defined in /etc/atmark/containers/*.conf with shell
syntax and the following parameters:

 - name: name of container, defaults to conf file basename
 - image: the image to start, either local name if updates are provided
   by swu or a full registry name (required to pull)
 - volumes, devices, ports: space separated list of respectively
   --volume, --device and --publish options
   note it is not possible to specify paths with space here, use
   append_args if necessary
 - readonly: toggle --read-only option, defaults to yes
 - pull: defaults to never, set to auto or always if required
 - autostart: set to no to disable autostart
 - restart: container restart policy (no, always, on-failure)
   Defaults to no.
 - pod: pod container belongs to
 - network: network container belongs to
 - ip: ip address assigned inside the container

additionally, one can use the append_args helper to add arbitrary
extra podman options as if they were invoking podman run like this;

    append_args --rootfs --restart always

and command to run inside image with set_command if required:

    set_command /bin/sh -c "complex; command"

pod-specific options:

 - infra_image: infra container image for the pod

network-specific options:

 - subnet: subnet assigned to network (CIDR syntax)

It is also possible to define pods and networks by setting type=pod
or type=network in such a configuration file.
pod take container networks argument (ports, network ip), while
networks can be assigned a subnet. Both also accept append_args
for extra options.

See examples in config_samples if required.

## podman_start

Parse simple config file and automatically start podman containers.

## podman_switch_storage

Alternate between tmpfs storage (default) or persistent storage.

persistent storage is likely necessary for development as saving large
containers is not possible with data on tmpfs, but switching is not
trivial so add a helper for it.

## podman_partial_image

Generate image file from tags or image ids.
If a base image/tag is given, remove objects from image file that
were used in base image.

## profile.d/podman.sh

(optional) checks and uses alternate atmark config files for interactive
use as well

## Example session

### 0. Prereq

- If cross-arch, setup binfmt
- podman, (optionally buildah)

### 1.a Create image: docker file

```
$ cd my_image_git
$ cat Dockerfile
ARG arch=arm64v8
ARG version=latest

FROM docker.io/${arch}/alpine:${version}

RUN apk update && apk upgrade
RUN apk add dependencies

COPY myscript /usr/local/bin/myscript
ENTRYPOINT /usr/local/bin/myscript
$ podman build -t my_image:1.0 .
```

### 1.b Create image: interactive

```
$ podman run -ti --rm --replace --name=my_cont docker.io/arm64v8/alpine:latest /bin/sh
# apk update && apk upgrade
# apk add dependencies
# ...
(other shell, do not close run command until after commit)
$ podman cp myscript my_cont:/usr/local/bin/my_script
$ podman commit --change ENTRYPOINT=/usr/local/bin/myscript my_cont my_image:1.0
(close initial shell, --rm will automatically cleanup temporary data)
```

### 1.c Create image 3: semi-interactive

```
$ tag=$(buildah from docker.io/arm64v8/alpine:latest)
$ buildah run $tag apk update
$ buildah run $tag apk upgrade
$ buildah run $tag apk add dependencies
$ buildah copy $tag myscript /usr/local/bin/myscript
$ buildah config --entrypoint /usr/local/bin/myscript $tag
$ buildah commit $tag my_image:1.0
$ buildah rm $tag
```


### 2.a Export image: registry

```
$ podman push --sign-by my-gpg-user my_image:1.0 podman.atmark-techno.com/company/my_image:1.0
$ podman push --sign-by my-gpg-user my_image:1.0 podman.atmark-techno.com/company/my_image:latest
```

Note: signing images includes the registry name in the signature,
so is not possible with other methods.
On the other hand, other methods embed the image file and validate
a hash from it, so the chain of trust is not broken.

### 2.b Export image: full image file

```
podman save --format oci-archive -o my_image-1.0.tar my_image:1.0
```

### 3.a Update image: docker file

Simply rebuild it:
```
$ podman build -t my_image:1.1 .
```

### 3.b Update image: interactive

```
$ podman run -ti --rm --replace --name=my_cont my_image:1.0 /bin/sh
# apk update && apk upgrade
(In other shell)
$ podman commit my_cont my_image:1.1
```

### 3.c Update image: semi-interactive

```
$ tag=$(buildah from my_image:1.0)
$ buildah run $tag apk update
$ buildah run $tag apk upgrade
$ buildah commit $tag my_image:1.1
$ buildah rm $tag
```

### 4.a Export updated image: registry

```
$ podman push --sign-by my-gpg-user my_image:1.1 podman.atmark-techno.com/company/my_image:1.1
$ podman push --sign-by my-gpg-user my_image:1.1 podman.atmark-techno.com/company/my_image:latest
```

### 4.b Export image: full image file

```
$ podman save --format oci-archive -o my_image-1.1.tar my_image:1.1
```

### 4.c Export image: partial image file

```
$ podman_partial_image -b my_image:1.0 -o my_image-1.1-from-1.0.tar my_image:1.1
```

### 5. Sanity check: the sizes look correct, and image is pullable:
```
$ ls -l my_image-*tar
-rw-r--r-- 1 martinet martinet  78M Mar  1 10:05 my_image-1.0.tar
-rw-r--r-- 1 martinet martinet  80M Mar  1 14:37 my_image-1.1.tar
-rw-r--r-- 1 martinet martinet 2.0M Mar  1 14:37 my_image-1.1-from-1.0.tar
$ podman rmi my_image:1.1
Untagged: localhost/my_image:1.1
Deleted: 3a6990719716f31429cd9230f5a7d64e141172266ed63dbe2196f6a54ba0c626
$ podman pull oci-archive:my_image-1.1-from-1.0.tar:'localhost/my_image:1.1'
Getting image source signatures
Copying blob 56d2cc464a85 skipped: already exists
Copying blob 6abc148b9f19 skipped: already exists
Copying blob 0b9912b28cef skipped: already exists
Copying blob ad676b889ebe skipped: already exists
Copying blob 1d5b3c07a6f6 skipped: already exists
Copying blob 1f8c192102cb done
Copying config 3a69907197 done
Writing manifest to image destination
Storing signatures
3a6990719716f31429cd9230f5a7d64e141172266ed63dbe2196f6a54ba0c626
$ podman image tree my_image:1.1
Image ID: 3a6990719716
Tags:     [localhost/my_image:1.1]
Size:     221.1MB
Image Layers
├──  ID: cb381a32b229 Size:  5.88MB Top Layer of: [docker.io/amd64/alpine:latest]
├──  ID: b53bb6b4eda7 Size: 4.608kB
├──  ID: a8b90a62b7a0 Size: 3.584kB
├──  ID: d20f1180ff65 Size: 213.1MB
├──  ID: b87fd3fb5764 Size: 11.78kB Top Layer of: [localhost/my_image:1.0]
└──  ID: 2ccbedb45391 Size: 2.156MB Top Layer of: [localhost/my_image:1.1]
```

