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"])
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue