Migrate teslamate to native Dagger container.py (#333)
## Summary - Replace legacy Dockerfile with native Dagger `container.py` build - Two-stage pipeline: Elixir+Node builder, Debian slim runtime - Uses shared helpers (`clone_from_forge`, `oci_labels`) - Delete old Dockerfile (pipeline auto-discovers container.py) - Update build-container-image docs and mark service reviewed ## Test plan - [x] `dagger call build --src=. --container-name=teslamate` succeeds locally - [ ] CI container build passes - [ ] Deploy from branch and verify teslamate starts cleanly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Reviewed-on: #333
This commit is contained in:
parent
4ca0630d76
commit
08c698e833
5 changed files with 108 additions and 87 deletions
|
|
@ -1,84 +0,0 @@
|
||||||
# TeslaMate - Tesla data logger
|
|
||||||
# Based on upstream Dockerfile
|
|
||||||
|
|
||||||
ARG CONTAINER_APP_VERSION=v3.0.0
|
|
||||||
ARG TESLAMATE_VERSION=${CONTAINER_APP_VERSION}
|
|
||||||
|
|
||||||
FROM elixir:1.19.5-otp-26 AS builder
|
|
||||||
|
|
||||||
ARG TESLAMATE_VERSION
|
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
||||||
|
|
||||||
RUN apt-get update \
|
|
||||||
&& apt-get install -y ca-certificates curl gnupg git zstd brotli \
|
|
||||||
&& mkdir -p /etc/apt/keyrings \
|
|
||||||
&& curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
|
|
||||||
| gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
|
|
||||||
&& NODE_MAJOR=22 \
|
|
||||||
&& echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" \
|
|
||||||
| tee /etc/apt/sources.list.d/nodesource.list \
|
|
||||||
&& apt-get update \
|
|
||||||
&& apt-get install nodejs -y \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN mix local.rebar --force && \
|
|
||||||
mix local.hex --force
|
|
||||||
|
|
||||||
# Clone specific version
|
|
||||||
RUN git clone --depth 1 --branch ${TESLAMATE_VERSION} \
|
|
||||||
https://forge.ops.eblu.me/mirrors/teslamate.git /opt/app
|
|
||||||
|
|
||||||
ENV MIX_ENV=prod
|
|
||||||
WORKDIR /opt/app
|
|
||||||
|
|
||||||
RUN mix deps.get --only $MIX_ENV
|
|
||||||
RUN mix deps.compile
|
|
||||||
|
|
||||||
RUN npm ci --prefix ./assets --progress=false --no-audit --loglevel=error
|
|
||||||
RUN mix assets.deploy
|
|
||||||
|
|
||||||
RUN mix compile
|
|
||||||
RUN SKIP_LOCALE_DOWNLOAD=true mix release --path /opt/built
|
|
||||||
|
|
||||||
# Runtime image
|
|
||||||
FROM debian:trixie-slim AS app
|
|
||||||
|
|
||||||
ARG CONTAINER_APP_VERSION
|
|
||||||
LABEL org.opencontainers.image.title="TeslaMate"
|
|
||||||
LABEL org.opencontainers.image.description="Tesla data logger and visualization"
|
|
||||||
LABEL org.opencontainers.image.version="${CONTAINER_APP_VERSION}"
|
|
||||||
LABEL org.opencontainers.image.source="https://forge.eblu.me/eblume/blumeops"
|
|
||||||
LABEL org.opencontainers.image.vendor="blumeops"
|
|
||||||
|
|
||||||
ENV LANG=C.UTF-8 \
|
|
||||||
SRTM_CACHE=/opt/app/.srtm_cache \
|
|
||||||
HOME=/opt/app
|
|
||||||
|
|
||||||
WORKDIR $HOME
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
libodbc2 \
|
|
||||||
libsctp1 \
|
|
||||||
libssl3t64 \
|
|
||||||
libstdc++6 \
|
|
||||||
netcat-openbsd \
|
|
||||||
tini \
|
|
||||||
tzdata \
|
|
||||||
&& apt-get clean \
|
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
|
||||||
&& groupadd --gid 10001 --system nonroot \
|
|
||||||
&& useradd --uid 10000 --system --gid nonroot --home-dir /home/nonroot --shell /sbin/nologin nonroot \
|
|
||||||
&& chown -R nonroot:nonroot .
|
|
||||||
|
|
||||||
COPY --chown=nonroot:nonroot --chmod=555 entrypoint.sh /
|
|
||||||
COPY --from=builder --chown=nonroot:nonroot /opt/built .
|
|
||||||
RUN mkdir $SRTM_CACHE
|
|
||||||
|
|
||||||
USER nonroot:nonroot
|
|
||||||
|
|
||||||
EXPOSE 4000
|
|
||||||
|
|
||||||
ENTRYPOINT ["tini", "--", "/bin/dash", "/entrypoint.sh"]
|
|
||||||
CMD ["bin/teslamate", "start"]
|
|
||||||
104
containers/teslamate/container.py
Normal file
104
containers/teslamate/container.py
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
"""TeslaMate — Tesla data logger.
|
||||||
|
|
||||||
|
Two-stage build: Elixir+Node (builder), Debian slim (runtime).
|
||||||
|
Source cloned from forge mirror.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import dagger
|
||||||
|
from dagger import dag
|
||||||
|
|
||||||
|
from blumeops.containers import clone_from_forge, oci_labels
|
||||||
|
|
||||||
|
VERSION = "v3.0.0"
|
||||||
|
|
||||||
|
|
||||||
|
async def build(src: dagger.Directory) -> dagger.Container:
|
||||||
|
source = clone_from_forge("teslamate", VERSION)
|
||||||
|
|
||||||
|
# Stage 1: Build Elixir release with Node.js assets
|
||||||
|
builder = (
|
||||||
|
dag.container()
|
||||||
|
.from_("elixir:1.19.5-otp-26")
|
||||||
|
.with_exec(
|
||||||
|
[
|
||||||
|
"bash",
|
||||||
|
"-c",
|
||||||
|
"apt-get update"
|
||||||
|
" && apt-get install -y ca-certificates curl gnupg git zstd brotli"
|
||||||
|
" && mkdir -p /etc/apt/keyrings"
|
||||||
|
" && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key"
|
||||||
|
" | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg"
|
||||||
|
' && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg]'
|
||||||
|
' https://deb.nodesource.com/node_22.x nodistro main"'
|
||||||
|
" > /etc/apt/sources.list.d/nodesource.list"
|
||||||
|
" && apt-get update"
|
||||||
|
" && apt-get install -y nodejs"
|
||||||
|
" && apt-get clean"
|
||||||
|
" && rm -rf /var/lib/apt/lists/*",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.with_exec(["mix", "local.rebar", "--force"])
|
||||||
|
.with_exec(["mix", "local.hex", "--force"])
|
||||||
|
.with_directory("/opt/app", source)
|
||||||
|
.with_workdir("/opt/app")
|
||||||
|
.with_env_variable("MIX_ENV", "prod")
|
||||||
|
.with_exec(["mix", "deps.get", "--only", "prod"])
|
||||||
|
.with_exec(["mix", "deps.compile"])
|
||||||
|
.with_exec(
|
||||||
|
[
|
||||||
|
"npm",
|
||||||
|
"ci",
|
||||||
|
"--prefix",
|
||||||
|
"./assets",
|
||||||
|
"--progress=false",
|
||||||
|
"--no-audit",
|
||||||
|
"--loglevel=error",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.with_exec(["mix", "assets.deploy"])
|
||||||
|
.with_exec(["mix", "compile"])
|
||||||
|
.with_exec(
|
||||||
|
["bash", "-c", "SKIP_LOCALE_DOWNLOAD=true mix release --path /opt/built"]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Stage 2: Debian slim runtime
|
||||||
|
entrypoint = src.file("containers/teslamate/entrypoint.sh")
|
||||||
|
|
||||||
|
runtime = (
|
||||||
|
dag.container()
|
||||||
|
.from_("debian:trixie-slim")
|
||||||
|
.with_exec(
|
||||||
|
[
|
||||||
|
"bash",
|
||||||
|
"-c",
|
||||||
|
"apt-get update && apt-get install -y --no-install-recommends"
|
||||||
|
" libodbc2 libsctp1 libssl3t64 libstdc++6"
|
||||||
|
" netcat-openbsd tini tzdata"
|
||||||
|
" && apt-get clean"
|
||||||
|
" && rm -rf /var/lib/apt/lists/*"
|
||||||
|
" && groupadd --gid 10001 --system nonroot"
|
||||||
|
" && useradd --uid 10000 --system --gid nonroot"
|
||||||
|
" --home-dir /home/nonroot --shell /sbin/nologin nonroot",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
runtime = oci_labels(
|
||||||
|
runtime,
|
||||||
|
title="TeslaMate",
|
||||||
|
description="Tesla data logger and visualization",
|
||||||
|
version=VERSION,
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
runtime.with_env_variable("LANG", "C.UTF-8")
|
||||||
|
.with_env_variable("SRTM_CACHE", "/opt/app/.srtm_cache")
|
||||||
|
.with_env_variable("HOME", "/opt/app")
|
||||||
|
.with_workdir("/opt/app")
|
||||||
|
.with_directory("/opt/app", builder.directory("/opt/built"), owner="nonroot")
|
||||||
|
.with_exec(["mkdir", "-p", "/opt/app/.srtm_cache"])
|
||||||
|
.with_file("/entrypoint.sh", entrypoint, permissions=0o555, owner="nonroot")
|
||||||
|
.with_user("nonroot")
|
||||||
|
.with_exposed_port(4000)
|
||||||
|
.with_entrypoint(["tini", "--", "/bin/dash", "/entrypoint.sh"])
|
||||||
|
.with_default_args(args=["bin/teslamate", "start"])
|
||||||
|
)
|
||||||
1
docs/changelog.d/teslamate-dagger-migration.infra.md
Normal file
1
docs/changelog.d/teslamate-dagger-migration.infra.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Migrate teslamate container build from legacy Dockerfile to native Dagger container.py.
|
||||||
|
|
@ -129,7 +129,7 @@ Existing containers demonstrate several build approaches:
|
||||||
| Native Dagger (Go + Node) | [[#navidrome]] | `container.py` with helper functions — preferred for new containers |
|
| Native Dagger (Go + Node) | [[#navidrome]] | `container.py` with helper functions — preferred for new containers |
|
||||||
| Alpine package install | [[#transmission]] | Simplest Dockerfile — install from apk |
|
| Alpine package install | [[#transmission]] | Simplest Dockerfile — install from apk |
|
||||||
| Go from source | [[#miniflux]] | Dockerfile: clone upstream, `go build` |
|
| Go from source | [[#miniflux]] | Dockerfile: clone upstream, `go build` |
|
||||||
| Multi-stage Elixir | [[#teslamate]] | Dockerfile: Elixir release with Node assets |
|
| Native Dagger (Elixir + Node) | [[#teslamate]] | `container.py` with Debian runtime — Elixir release with Node assets |
|
||||||
| Runtime tarball download | [[#kiwix-serve]] | Dockerfile: download pre-built binary with arch detection |
|
| Runtime tarball download | [[#kiwix-serve]] | Dockerfile: download pre-built binary with arch detection |
|
||||||
| Nix `dockerTools` | [[#ntfy-nix]] | `buildLayeredImage` with nix-built app (ringtail runner) |
|
| Nix `dockerTools` | [[#ntfy-nix]] | `buildLayeredImage` with nix-built app (ringtail runner) |
|
||||||
|
|
||||||
|
|
@ -147,7 +147,7 @@ Existing containers demonstrate several build approaches:
|
||||||
|
|
||||||
### teslamate
|
### teslamate
|
||||||
|
|
||||||
`containers/teslamate/Dockerfile` — Two-stage Elixir build with Node.js asset compilation. Uses Debian-based images due to Elixir/OTP dependencies. (Legacy Dockerfile — migrate to `container.py` during review.)
|
`containers/teslamate/container.py` — Native Dagger build. Two-stage pipeline: Elixir builder with Node.js for asset compilation, Debian slim runtime. Uses Debian-based images (not Alpine) due to Elixir/OTP dependencies. Includes entrypoint script for pg-wait and migrations.
|
||||||
|
|
||||||
### kiwix-serve
|
### kiwix-serve
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ services:
|
||||||
|
|
||||||
- name: teslamate
|
- name: teslamate
|
||||||
type: argocd
|
type: argocd
|
||||||
last-reviewed: 2026-03-03
|
last-reviewed: 2026-04-14
|
||||||
current-version: "v3.0.0"
|
current-version: "v3.0.0"
|
||||||
upstream-source: https://github.com/teslamate-org/teslamate/releases
|
upstream-source: https://github.com/teslamate-org/teslamate/releases
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue