Skip to content

Demo app duplicated in 5 languages (Go/JavaScript/Python/Ruby/Rust) showing how to go from source code to container image using melange+apko

License

Notifications You must be signed in to change notification settings

OscarAyoy/hello-melange-apko

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

66 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hello-melange-apko 💫

go js py ruby rust

This repo contains an example app duplicated across 5 languages showing how to:

  • Package source code into APKs using melange
  • Build and publish OCI images from APKs using apko

The app itself is a basic HTTP server that returns "Hello World!"

$ curl -s http://localhost:8080
Hello World!

Wondering what "APKs" are? They're OS packages with a .apk extension (similar to .rpm / .deb) that are compatible with apk.

Variations

Language Repo Path GitHub Action Notes
Go go/ go.yml uses gin
JavaScript js/ js.yml uses express, vendors node_modules, depends on nodejs
Python py/ py.yml uses flask, vendors virtualenv, depends on python3
Ruby ruby/ ruby.yml uses sinatra, vendors bundle, depends on ruby
Rust rust/ rust.yml uses hyper, currently builds very slow cross-platform

Note: third-party server frameworks are used intentionally to validate the use of dependencies.

"The hard way"

This section shows how to run through each of the build stages locally and pushing an image to GHCR.

Requirements:

Note: these steps should also work without docker on an apk-based Linux distribution such as Alpine.

Change directory

All of the following steps in this section assume that from the root of this repository, you have changed directory to one of the variations:

cd go/   # for Go
cd js/   # for JavaScript
cd py/   # for Python
cd ruby/ # for Ruby
cd rust/ # for Rust

Build apks with melange

Make sure the packages/ directory is removed:

rm -rf ./packages/

Create a temporary melange keypair:

docker run --rm -v "${PWD}":/work distroless.dev/melange keygen

Build an apk for all architectures using melange:

docker run --rm --privileged -v "${PWD}":/work \
    distroless.dev/melange build melange.yaml \
    --arch amd64,aarch64,armv7 \
    --repository-append packages --signing-key melange.rsa

To debug the above:

docker run --rm --privileged -it -v "${PWD}":/work \
    --entrypoint sh \
    distroless.dev/melange

# Build apks (use just --arch amd64 to isolate issue)
melange build melange.yaml \
    --arch amd64,aarch64,armv7 \
    --repository-append packages --signing-key melange.rsa

# Install an apk
apk add ./packages/x86_64/hello-server-*.apk --allow-untrusted --force-broken-world

# Delete an apk
apk del hello-server --force-broken-world

Build image with apko

Note: you could skip this step and go to "Push image with apko".

Build an apk for all architectures using melange:

# Your GitHub username
GITHUB_USERNAME="myuser"
REF="ghcr.io/${GITHUB_USERNAME}/hello-melange-apko/$(basename "${PWD}")"

docker run --rm -v "${PWD}":/work \
    distroless.dev/apko build --debug apko.yaml \
    "${REF}" output.tar -k melange.rsa.pub \
    --build-arch amd64,aarch64,armv7

If you do not wish to push the image, you could load it directly:

docker load < output.tar
docker run --rm --rm -p 8080:8080  "${REF}"

To debug the above:

docker run --rm -it -v "${PWD}":/work \
    -e REF="${REF}" \
    --entrypoint sh \
    distroless.dev/apko

# Build image (use just --build-arch amd64 to isolate issue)
apko build --debug apko.yaml "${REF}" output.tar -k melange.rsa.pub --build-arch amd64,aarch64,armv7

Push image with apko

Build and push an image to, for example, GHCR:

# Your GitHub username
GITHUB_USERNAME="myuser"
REF="ghcr.io/${GITHUB_USERNAME}/hello-melange-apko/$(basename "${PWD}")"

# A personal access token with the "write:packages" scope
GITHUB_TOKEN="*****"

docker run --rm -v "${PWD}":/work \
    -e REF="${REF}" \
    -e GITHUB_USERNAME="${GITHUB_USERNAME}" \
    -e GITHUB_TOKEN="${GITHUB_TOKEN}" \
    --entrypoint sh \
    distroless.dev/apko -c \
        'echo "${GITHUB_TOKEN}" | \
            apko login ghcr.io -u "${GITHUB_USERNAME}" --password-stdin && \
            apko publish --debug apko.yaml \
                "${REF}" -k melange.rsa.pub \
                --arch amd64,aarch64,armv7'

Sign image with cosign

After the image has been published, sign it recursively using cosign:

# Your GitHub username
GITHUB_USERNAME="myuser"
REF="ghcr.io/${GITHUB_USERNAME}/hello-melange-apko/$(basename "${PWD}")"

COSIGN_EXPERIMENTAL=1 cosign sign -r -y -f "${REF}"

This should use "keyless" mode and open a browser window for you to authenticate.

Note: prior to running above, you may need to re-login to GHCR on the host using docker (or other tool):

# Your GitHub username
GITHUB_USERNAME="myuser"

# A personal access token with the "write:packages" scope
GITHUB_TOKEN="*****"

echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${GITHUB_USERNAME}" --password-stdin

Verify the signature

Verify that the image is signed using cosign:

# Your GitHub username
GITHUB_USERNAME="myuser"
REF="ghcr.io/${GITHUB_USERNAME}/hello-melange-apko/$(basename "${PWD}")"

COSIGN_EXPERIMENTAL=1 cosign verify "${REF}"

Run the hello server image

Finally, run the image using docker:

# Your GitHub username
GITHUB_USERNAME="myuser"
REF="ghcr.io/${GITHUB_USERNAME}/hello-melange-apko/$(basename "${PWD}")"

docker run --rm --rm -p 8080:8080 "${REF}"

Then in another terminal, try hitting the server using curl:

curl -s http://localhost:8080
Hello World!

About

Demo app duplicated in 5 languages (Go/JavaScript/Python/Ruby/Rust) showing how to go from source code to container image using melange+apko

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 34.9%
  • JavaScript 27.7%
  • Go 18.3%
  • Ruby 11.8%
  • Python 7.3%