Skip to content

Commit

Permalink
feat(infra): add Dockerfile for build
Browse files Browse the repository at this point in the history
Up until now pg_idkit was hard to use from a dockerized environment
without building a custom image and adding the dockerfile explicitly.

This commit adds a Dockerfile and related build machinery which
creates a Postgres image with pg_idkit pre-installed and usable.

Along with building locally, the pg_idkit repository will also build
and push images on release tags.

Signed-off-by: vados <[email protected]>
  • Loading branch information
t3hmrman committed Nov 27, 2023
1 parent 9c2cf66 commit 328842f
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 43 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/container.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Build pg_idkit container

on:
- push

jobs:
build:
runs-on: ${{ matrix.config.gh.runner }}
matrix:
config:
- triple: x86_64-unknown-linux-musl
gh:
runner: ubuntu-22.04
container:
arch: amd64
pg_version: 15.5
os_version: alpine3.18

# - triple: x86_64-unknown-linux-gnu
# gh_runner: ubuntu-22.04
# pg_img_version: 15.5
# os_img_version:
# container:
# arch: amd64

# - triple: x86_64-unknown-linux-gnu
# runner: ubuntu-22.04
# os: alpine
# container_arch: amd64

# - triple: aarch64-unknown-linux-gnu
# runner: ubuntu-latest
# os: alpine
# arch: aarch64
# - triple: aarch64-unknown-linux-musl
# runner: ubuntu-latest
# os: alpine
# arch: aarch64
# - triple: aarch64-apple-darwin
# runner: macos-12
# os: alpine
# arch: aarch64
# - triple: x86_64-apple-darwin
# runner: macos-12
# os: alpine
# arch: aarch64

steps:
- uses: actions/checkout@v3
- uses: docker/setup-qemu-action@v3
- uses: extractions/setup-just@v1

# - name: Switch docker buildx
# run: docker buildx create --name buildx --use

- name: Build the multi-platform image
run: just image
env:
CONTAINER_IMAGE_ARCH: ${{ matrix.config.container.arch }}
POSTGRES_IMAGE_VERSION: ${{ matrix.config.container.pg_version }}
POSTGRES_OS_IMAGE_VERSION: ${{ matrix.config.container.os_version }}

# env:
# DOCKER_PLATFORM_ARG: >-
# --platform linux/amd64,linux/arm64,linux/arm/v7

59 changes: 46 additions & 13 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,24 @@ _check-installed-version tool msg:
#########

version := `grep 'version' Cargo.toml | head -n 1 | sed -rn 's/version\s*=\s*(.*)/\1/p'`
revision := `git rev-parse --short HEAD`

# NOTE: we can't use this as the official version getter until
# see: https://github.com/nicolaiunrein/cargo-get/issues/14
@get-version: _check-tool-cargo-get
cargo get package.version

@get-revision: _check-tool-cargo-get
echo -n {{revision}}

print-version:
#!/usr/bin/env -S bash -euo pipefail
echo -n `{{just}} get-version`

print-revision:
#!/usr/bin/env -S bash -euo pipefail
echo -n `{{just}} get-revision`

changelog:
{{git}} cliff --unreleased --tag=$(VERSION) --prepend=$(CHANGELOG_FILE_PATH)

Expand All @@ -57,8 +65,11 @@ build-watch: _check-tool-cargo _check-tool-cargo-watch
build-test-watch: _check-tool-cargo _check-tool-cargo-watch
{{cargo_watch}} -x "test $(CARGO_BUILD_FLAGS)" --watch src

pkg_pg_version := env_var_or_default("PKG_PG_VERSION", "15.5")
pkg_pg_config_path := env_var_or_default("PKG_PG_CONFIG_PATH", "~/.pgrx/" + pkg_pg_version + "/pgrx-install/bin/pg_config")

package:
{{cargo}} pgrx package
{{cargo}} pgrx package --pg-config {{pkg_pg_config_path}}

test:
{{cargo}} test
Expand All @@ -68,24 +79,23 @@ test:
# Docker #
##########

pg_image_version := env_var_or_default("POSTGRES_IMAGE_VERSION", "15.4")
pg_image_tag := env_var_or_default("POSGRES_IMAGE_VERSION", pg_image_version + "-alpine3.18")
container_img_arch := env_var_or_default("CONTAINER_IMAGE_ARCH", "amd64")

pgkit_image_name := env_var_or_default("PGKIT_IMAGE_NAME", "postgres")
pgkit_image_tag := env_var_or_default("PGKIT_IMAGE_TAG", pg_image_version + "-pg_idkit=" + version)
pgkit_image_name_full := env_var_or_default("PGKIT_IMAGE_NAME_FULL", pgkit_image_name + ":" + pgkit_image_tag)
pgkit_dockerfile_path := env_var_or_default("PGKIT_DOCKERFILE_PATH", "infra" / "docker" / pgkit_image_tag + ".Dockerfile")
pg_image_version := env_var_or_default("POSTGRES_IMAGE_VERSION", "15.5")
pg_os_image_version := env_var_or_default("POSTGRES_OS_IMAGE_VERSION", "alpine3.18")

ci_dockerfile_path := env_var_or_default("CI_DOCKERFILE_PATH", "infra" / "docker" / "ci.Dockerfile")
ci_image_name := env_var_or_default("CI_IMAGE_NAME", "ghcr.io/vadosware/pg_idkit/builder")
ci_image_tag := env_var_or_default("CI_IMAGE_TAG", "0.x.x")
ci_image_name_full := env_var_or_default("CI_IMAGE_NAME_FULL", ci_image_name + ":" + ci_image_tag)
pgidkit_image_name := env_var_or_default("PGIDKIT_IMAGE_NAME", "pg_idkit")
pgidkit_image_tag := env_var_or_default("POSGRES_IMAGE_VERSION", "pg" + pg_image_version + "-" + pg_os_image_version + "-" + container_img_arch)
pgidkit_image_name_full := env_var_or_default("PGIDKIT_IMAGE_NAME_FULL", pgidkit_image_name + ":" + pgidkit_image_tag)
pgidkit_dockerfile_path := env_var_or_default("PGIDKIT_DOCKERFILE_PATH", "infra" / "docker" / pgidkit_image_tag + ".Dockerfile")

docker_password_path := env_var_or_default("DOCKER_PASSWORD_PATH", "secrets/docker/password.secret")
docker_username_path := env_var_or_default("DOCKER_USERNAME_PATH", "secrets/docker/username.secret")
docker_image_registry := env_var_or_default("DOCKER_IMAGE_REGISTRY", "ghcr.io/vadosware/pg_idkit")
docker_config_dir := env_var_or_default("DOCKER_CONFIG", "secrets/docker")

img_dockerfile_path := "infra" / "docker" / "pg" + pg_image_version + "-" + pg_os_image_version + "-" + container_img_arch + ".Dockerfile"

# Ensure that that a given file is present
_ensure-file file:
#!/usr/bin/env -S bash -euo pipefail
Expand All @@ -101,9 +111,17 @@ docker-login:
cat {{docker_password_path}} | {{docker}} login {{docker_image_registry}} -u `cat {{docker_username_path}}` --password-stdin
cp {{docker_config_dir}}/config.json {{docker_config_dir}}/.dockerconfigjson

docker_platform_arg := env_var_or_default("DOCKER_PLATFORM_ARG", "")
docker_progress_arg := env_var_or_default("DOCKER_PROGRESS_ARG", "")

# Build the docker image for pg_idkit
image:
{{docker}} build -f {{pgkit_dockerfile_path}} -t {{pgkit_image_name_full}}
build-image:
{{docker}} build {{docker_platform_arg}} {{docker_progress_arg}} -f {{img_dockerfile_path}} -t {{pgidkit_image_name_full}} --build-arg PGIDKIT_REVISION={{revision}} .

ci_dockerfile_path := env_var_or_default("CI_DOCKERFILE_PATH", "infra" / "docker" / "ci.Dockerfile")
ci_image_name := env_var_or_default("CI_IMAGE_NAME", "ghcr.io/vadosware/pg_idkit/builder")
ci_image_tag := env_var_or_default("CI_IMAGE_TAG", "0.x.x")
ci_image_name_full := env_var_or_default("CI_IMAGE_NAME_FULL", ci_image_name + ":" + ci_image_tag)

# Build the docker image used in CI
build-ci-image:
Expand All @@ -112,3 +130,18 @@ build-ci-image:
# Push the docker image used in CI (to GitHub Container Registry)
push-ci-image:
{{docker}} push {{ci_image_name_full}}

# Determine the Dockerfile to use when building the packaging utility base image
base_pkg_dockerfile_path := if pg_os_image_version == "alpine3.18" {
"infra/docker/base-pkg-alpine3.18.Dockerfile"
} else if pg_os_image_version == "bookworm" {
"infra/docker/base-pkg-bookworm.Dockerfile"
} else {
error("invalid pg_os_image_version")
}
base_pkg_image_name := env_var_or_default("PKG_IMAGE_NAME", "ghcr.io/vadosware/pg_idkit/base-pkg")
base_pkg_image_name_full := env_var_or_default("PKG_IMAGE_NAME_FULL", base_pkg_image_name + ":" + pgidkit_image_tag)

# Build the base cache image for packaging
build-base-pkg-image:
{{docker}} build -f {{base_pkg_dockerfile_path}} . -t {{base_pkg_image_name_full}};
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

`pg_idkit` is a [Postgres][postgres] extension for generating IDs. It aims to be have just about every ID you'd normally think of using:

| Methodology | function | Crate | Description |
|------------------------|----------------------------|---------------------------------------------------------|----------------------------------------------------------|
| [UUID v6][uuidv6] | `idkit_uuidv6_generate` | [`uuidv6`](https://crates.io/crates/uuidv6) | UUID v6 ([RFC 4122][rfc-4122-update]) |
| [UUID v7][uuidv7] | `idkit_uuidv7_generate` | [`uuid7`](https://crates.io/crates/uuid7) | UUID v7 ([RFC 4122][rfc-4122-update]) |
| [nanoid][nanoid] | `idkit_nanoid_generate` | [`nanoid`](https://crates.io/crates/nanoid) | NanoID, developed by [Andrey Sitnik][github-ai] |
| [ksuid][ksuid] | `idkit_ksuid_generate` | [`ksuid`](https://crates.io/crates/ksuid) | developed by [Segment][segment] |
| [ulid][ulid] | `idkit_ulid_generate` | [`ulid`](https://crates.io/crates/ulid) | unique, lexicographically sortable identifiers |
| [Timeflake][timeflake] | `idkit_timeflake_generate` | [`timeflake-rs`](https://crates.io/crates/timeflake-rs) | Twitter's Snowflake + Instagram's ID + Firebase's PushID |
| [PushID][pushid] | `idkit_pushid_generate` | [`pushid`](https://crates.io/crates/pushid) | Google Firebase's PushID |
| [xid][xid] | `idkit_xid_generate` | [`xid`](https://crates.io/crates/xid) | XID |
| [cuid][cuid] (deprecated) | `idkit_cuid_generate` | [`cuid`](https://crates.io/crates/cuid) | CUID |
| [cuid2][cuid2] | `idkit_cuid2_generate` | [`cuid2`](https://crates.io/crates/cuid2) | CUID |
| Methodology | function | Crate | Description |
|---------------------------|----------------------------|---------------------------------------------------------|----------------------------------------------------------|
| [UUID v6][uuidv6] | `idkit_uuidv6_generate` | [`uuidv6`](https://crates.io/crates/uuidv6) | UUID v6 ([RFC 4122][rfc-4122-update]) |
| [UUID v7][uuidv7] | `idkit_uuidv7_generate` | [`uuid7`](https://crates.io/crates/uuid7) | UUID v7 ([RFC 4122][rfc-4122-update]) |
| [nanoid][nanoid] | `idkit_nanoid_generate` | [`nanoid`](https://crates.io/crates/nanoid) | NanoID, developed by [Andrey Sitnik][github-ai] |
| [ksuid][ksuid] | `idkit_ksuid_generate` | [`ksuid`](https://crates.io/crates/ksuid) | developed by [Segment][segment] |
| [ulid][ulid] | `idkit_ulid_generate` | [`ulid`](https://crates.io/crates/ulid) | unique, lexicographically sortable identifiers |
| [Timeflake][timeflake] | `idkit_timeflake_generate` | [`timeflake-rs`](https://crates.io/crates/timeflake-rs) | Twitter's Snowflake + Instagram's ID + Firebase's PushID |
| [PushID][pushid] | `idkit_pushid_generate` | [`pushid`](https://crates.io/crates/pushid) | Google Firebase's PushID |
| [xid][xid] | `idkit_xid_generate` | [`xid`](https://crates.io/crates/xid) | XID |
| [cuid][cuid] (deprecated) | `idkit_cuid_generate` | [`cuid`](https://crates.io/crates/cuid) | CUID |
| [cuid2][cuid2] | `idkit_cuid2_generate` | [`cuid2`](https://crates.io/crates/cuid2) | CUID |

This Postgres extension is made possible thanks to [`pgrx`][pgrx].

Expand Down Expand Up @@ -76,7 +76,7 @@ cargo install --locked just

#### `cargo-pgrx`

Installing
Installing

```console
cargo install --locked cargo-pgrx
Expand Down Expand Up @@ -179,6 +179,7 @@ export DOCKER_CONFIG=$(realpath secrets/docker)
[google]: https://google.com
[instagram]: instagram-engineering.com/
[it-cabrera]: https://darkghosthunter.medium.com/
[just]: https://github.com/casey/just
[ksuid]: https://github.com/segmentio/ksuid
[mongodb]: https://www.mongodb.com/blog/channel/engineering-blog
[nanoid]: https://www.npmjs.com/package/nanoid
Expand Down
17 changes: 0 additions & 17 deletions infra/docker/14.4-alpine.Dockerfile

This file was deleted.

35 changes: 35 additions & 0 deletions infra/docker/base-pkg-alpine3.18.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
FROM postgres:15.5-alpine3.18@sha256:a57387207806d947c842f1be9f358e37b05442bf8b5ed19b1a69af281be930e7 AS builder

ARG RUST_TOOLCHAIN_VERSION=1.74
ARG PGRX_PG_VERSION=pg15

# Install OS deps
RUN apk add --no-cache \
alpine-sdk \
clang \
clang-dev \
clang-libs \
musl-dev \
openssl-dev \
rustup

# Install Rust & related deps
RUN rustup-init -y --profile minimal --default-toolchain $RUST_TOOLCHAIN_VERSION \
&& source "$HOME/.cargo/env" \
&& cargo install cargo-binstall
ENV PATH="/root/.cargo/bin:${PATH}"
RUN cargo binstall -y just

# Install pgrx
# (disabling the static C runtime is required since pgrx requires dynamic linking w/ libssl and libcrypto)
RUN RUSTFLAGS="-Ctarget-feature=-crt-static" cargo install cargo-pgrx

# Copy in pg_idkit code
WORKDIR /pg_idkit
COPY . .

# Perform the build and packaging of pg_idkit
ENV PGRX_IGNORE_RUST_VERSIONS=y
ENV PKG_PG_CONFIG_PATH=/usr/local/bin/pg_config
RUN cargo pgrx init --pg15=$PKG_PG_CONFIG_PATH
RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package
36 changes: 36 additions & 0 deletions infra/docker/pg15.5-alpine3.18-amd64.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# NOTE: you must have the base packaging layer built for this image to work
# you can build this from scratch with `just build-base-pkg-image`
#
FROM ghcr.io/vadosware/pg_idkit/base-pkg:pg15.5-alpine3.18-amd64 AS builder

# Re-run the build with the latest code
WORKDIR /pg_idkit
COPY . .
RUN RUSTFLAGS="-Ctarget-feature=-crt-static" just build package

FROM postgres:15.5-alpine3.18@sha256:a57387207806d947c842f1be9f358e37b05442bf8b5ed19b1a69af281be930e7

# NOTE: PGRX_PG_VERSION is defined via base-pkg:pg15.5-alpine3.18-amd64
ARG PGRX_PG_VERSION=pg15
ARG PGIDKIT_REVISION

# Copy relevant built-files
COPY --from=builder /pg_idkit/target/release/pg_idkit-${PGRX_PG_VERSION}/usr /usr

# expected @ /usr/local/share/postgresql/extension
# actually @ ./local/share/postgresql/extension/pg_idkit.control

ARG PGIDKIT_VERSION
ARG PGIDKIT_REVISION

LABEL org.opencontainers.image.authors="Victor Adossi <[email protected]>"
LABEL org.opencontainers.image.description="A distribution of the base postgres image, with pg_idkit pre-installed."
LABEL org.opencontainers.image.documentation="https://github.com/VADOSWARE/pg_idkit#readme"
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.revision=$PGIDKIT_REVISION
LABEL org.opencontainers.image.source="https://github.com/VADOSWARE/pg_idkit"
LABEL org.opencontainers.image.title="Postgres + pg_idkit"
LABEL org.opencontainers.image.url="https://github.com/VADOSWARE/pg_idkit"
LABEL org.opencontainers.image.vendor="VADOSWARE"
LABEL org.opencontainers.image.version=v${PGIDKIT_VERSION}

0 comments on commit 328842f

Please sign in to comment.