mirror of
https://github.com/linuxserver/docker-homeassistant.git
synced 2026-01-09 07:11:51 +08:00
271 lines
9.3 KiB
Docker
271 lines
9.3 KiB
Docker
# syntax=docker/dockerfile:1
|
|
|
|
FROM ghcr.io/linuxserver/baseimage-alpine:3.22
|
|
|
|
# set version label
|
|
ARG BUILD_DATE
|
|
ARG VERSION
|
|
ARG HASS_RELEASE
|
|
LABEL build_version="Linuxserver.io version:- ${VERSION} Build-date:- ${BUILD_DATE}"
|
|
LABEL maintainer="saarg, roxedus"
|
|
|
|
ENV \
|
|
S6_SERVICES_GRACETIME=240000 \
|
|
UV_SYSTEM_PYTHON=true \
|
|
UV_NO_CACHE=true \
|
|
UV_EXTRA_INDEX_URL="https://wheels.home-assistant.io/musllinux-index/" \
|
|
ATTACHED_DEVICES_PERMS="/dev/ttyACM* /dev/ttyUSB* -type c"
|
|
|
|
COPY root/etc/pip.conf /etc/
|
|
|
|
# install packages
|
|
RUN \
|
|
echo "**** install build packages ****" && \
|
|
apk add --no-cache --virtual=build-dependencies \
|
|
autoconf \
|
|
patch \
|
|
bzip2-dev \
|
|
coreutils \
|
|
dpkg-dev dpkg \
|
|
expat-dev \
|
|
findutils \
|
|
build-base \
|
|
gdbm-dev \
|
|
libc-dev \
|
|
libffi-dev \
|
|
libnsl-dev \
|
|
openssl \
|
|
openssl-dev \
|
|
libtirpc-dev \
|
|
linux-headers \
|
|
make \
|
|
mpdecimal-dev \
|
|
ncurses-dev \
|
|
pax-utils \
|
|
readline-dev \
|
|
sqlite-dev \
|
|
tcl-dev \
|
|
tk \
|
|
tk-dev \
|
|
xz-dev \
|
|
zlib-dev \
|
|
bluez-dev && \
|
|
echo "**** install runtime packages ****" && \
|
|
apk add --no-cache \
|
|
bind-tools \
|
|
bluez \
|
|
bluez-deprecated \
|
|
bluez-libs \
|
|
cups-libs \
|
|
curl \
|
|
eudev-libs \
|
|
ffmpeg \
|
|
git \
|
|
hwdata-usb \
|
|
imlib2 \
|
|
iperf3 \
|
|
iputils \
|
|
libcap \
|
|
libftdi1 \
|
|
libgpiod \
|
|
libturbojpeg \
|
|
libpulse \
|
|
libstdc++ \
|
|
libxslt \
|
|
libzbar \
|
|
mariadb-connector-c \
|
|
net-tools \
|
|
nmap \
|
|
openssh-client \
|
|
openssl \
|
|
pianobar \
|
|
postgresql-libs \
|
|
pulseaudio-alsa \
|
|
socat \
|
|
tiff \
|
|
xz && \
|
|
echo "**** Retrieve versions ****" && \
|
|
mkdir -p \
|
|
/tmp/core && \
|
|
if [ -z ${HASS_RELEASE+x} ]; then \
|
|
HASS_RELEASE=$(curl -sX GET https://api.github.com/repos/home-assistant/core/releases/latest \
|
|
| jq -r .tag_name); \
|
|
fi && \
|
|
echo "HASS_RELEASE retrieved as ${HASS_RELEASE}" && \
|
|
curl -o \
|
|
/tmp/core.tar.gz -L \
|
|
"https://github.com/home-assistant/core/archive/${HASS_RELEASE}.tar.gz" && \
|
|
tar xf \
|
|
/tmp/core.tar.gz -C \
|
|
/tmp/core --strip-components=1 && \
|
|
HASS_BASE=$(cat /tmp/core/.github/workflows/builder.yml \
|
|
| grep 'BASE_IMAGE_VERSION: ' \
|
|
| sed 's|.*: "||' | sed 's|".*||') && \
|
|
echo "HASS_BASE retrieved as ${HASS_BASE}" && \
|
|
HA_PY_MAJOR=$(curl -fsL https://raw.githubusercontent.com/home-assistant/docker/${HASS_BASE}/build.yaml \
|
|
| grep 'amd64: ' \
|
|
| cut -d: -f3 \
|
|
| sed 's|-alpine.*||') && \
|
|
echo "HA_PY_MAJOR retrieved as ${HA_PY_MAJOR}" && \
|
|
HASS_BASE_RELEASE=$(curl -fSsL https://api.github.com/repos/home-assistant/docker/releases) && \
|
|
HASS_BASE_TIME=$(date -d $(echo $HASS_BASE_RELEASE | \
|
|
jq -r ".[] | select(.tag_name | match(\"${HASS_BASE}\")) .published_at") +%s) && \
|
|
for i in 0 1 2 3 4 5 6; do \
|
|
HA_DOCKER_BASE_TIME=$(date -d $(curl -s "https://api.github.com/repos/home-assistant/docker-base/releases" | \
|
|
jq -r ".[${i}].published_at") +%s); \
|
|
if [ "${HASS_BASE_TIME}" -ge "${HA_DOCKER_BASE_TIME}" ]; then \
|
|
HA_DOCKER_BASE=$(curl -s "https://api.github.com/repos/home-assistant/docker-base/releases" | jq -r ".[${i}].tag_name"); \
|
|
echo "**** HA_DOCKER_BASE detected as version ${HA_DOCKER_BASE} ****"; \
|
|
break; \
|
|
fi; \
|
|
done && \
|
|
git clone --branch "${HA_DOCKER_BASE}" \
|
|
--depth 1 https://github.com/home-assistant/docker-base.git \
|
|
/tmp/ha-docker-base && \
|
|
HA_PY_VERSION=$(cat /tmp/ha-docker-base/python/${HA_PY_MAJOR}/build.yaml \
|
|
| grep 'PYTHON_VERSION: ' \
|
|
| sed 's|.*PYTHON_VERSION: ||' \
|
|
| sed 's|"||g') && \
|
|
HA_JEMALLOC_VER=$(cat /tmp/ha-docker-base/alpine/build.yaml \
|
|
| grep 'JEMALLOC_VERSION: ' \
|
|
| sed 's|.*JEMALLOC_VERSION: ||' \
|
|
| sed 's|"||g') && \
|
|
HA_ALPINE_VER=$(curl -fsL https://raw.githubusercontent.com/home-assistant/docker/${HASS_BASE}/build.yaml \
|
|
| grep 'amd64: ' \
|
|
| cut -d: -f3 \
|
|
| sed 's|.*-alpine||' \
|
|
| sed 's|-.*||') && \
|
|
IMAGE_ALPINE_VER=$(cat /etc/os-release | grep PRETTY_NAME | sed 's|.*Linux v||' | sed 's|"||') && \
|
|
if [[ "${HA_ALPINE_VER}" != "${IMAGE_ALPINE_VER}" ]]; then \
|
|
echo -e "**** Incorrect OS version detected, canceling build ****\n**** Upstream expected OS: ${HA_ALPINE_VER} ****\n**** Detected OS: ${IMAGE_ALPINE_VER}****"; \
|
|
exit 1; \
|
|
fi && \
|
|
HA_PIP_VERSION=$(cat /tmp/ha-docker-base/python/${HA_PY_MAJOR}/build.yaml \
|
|
| grep 'PIP_VERSION: ' \
|
|
| sed 's|.*PIP_VERSION: ||' \
|
|
| sed 's|"||g') && \
|
|
HA_UV_VERSION=$(curl -fsL "https://raw.githubusercontent.com/home-assistant/core/refs/tags/${HASS_RELEASE}/Dockerfile" | grep 'install uv==' | sed 's|.*install uv==||') && \
|
|
HA_GO2RTC_VERSION=$(curl -fsL "https://raw.githubusercontent.com/home-assistant/core/refs/tags/${HASS_RELEASE}/homeassistant/components/go2rtc/const.py" | grep 'RECOMMENDED_VERSION' | sed 's|.*RECOMMENDED_VERSION = "||' | sed 's|".*||') && \
|
|
curl -o \
|
|
/bin/go2rtc -fL \
|
|
"https://github.com/AlexxIT/go2rtc/releases/download/v${HA_GO2RTC_VERSION}/go2rtc_linux_amd64" && \
|
|
chmod +x /bin/go2rtc && \
|
|
echo "**** Quick test go2rtc binary: ****" && \
|
|
/bin/go2rtc --version && \
|
|
echo "**** install jemalloc ****" && \
|
|
git clone --branch ${HA_JEMALLOC_VER} \
|
|
--depth 1 "https://github.com/jemalloc/jemalloc" \
|
|
/tmp/jemalloc && \
|
|
cd /tmp/jemalloc && \
|
|
./autogen.sh \
|
|
--with-lg-page=16 && \
|
|
make -j "$(nproc)" && \
|
|
make install_lib_shared install_bin && \
|
|
echo "**** install python ****" && \
|
|
PY_HA_ALPINE_VER=$(echo "${HA_ALPINE_VER}" | sed 's|\.||') && \
|
|
PY_RELEASE_TAG=$(curl -s https://api.github.com/repos/linuxserver/docker-python/releases \
|
|
| jq -r "first(.[] | select(.tag_name | startswith(\"alpine${PY_HA_ALPINE_VER}-${HA_PY_VERSION}\"))) | .tag_name") && \
|
|
if [ -n "${PY_RELEASE_TAG}" ]; then \
|
|
echo "**** Installing python from the linuxserver python repo release ${PY_RELEASE_TAG} ****" && \
|
|
curl -o \
|
|
/tmp/python.tar.gz -L \
|
|
"https://github.com/linuxserver/docker-python/releases/download/${PY_RELEASE_TAG}/python-amd64.tar.gz" && \
|
|
tar xf \
|
|
/tmp/python.tar.gz -C \
|
|
/usr/local && \
|
|
apk add --no-cache $(cat /usr/local/python-deps.txt); \
|
|
else \
|
|
echo "**** Python version ${HA_PY_VERSION} not found in the linuxserver repo, compiling from source ****" && \
|
|
mkdir -p /tmp/python && \
|
|
curl -o \
|
|
/tmp/python.tar.xz -L \
|
|
"https://www.python.org/ftp/python/${HA_PY_VERSION}/Python-${HA_PY_VERSION}.tar.xz" && \
|
|
tar xf \
|
|
/tmp/python.tar.xz -C \
|
|
/tmp/python --strip-components=1 && \
|
|
for patch in /tmp/ha-docker-base/python/${HA_PY_MAJOR}/*.patch; do \
|
|
patch -d /tmp/python -p 1 < "${patch}"; \
|
|
done && \
|
|
cd /tmp/python && \
|
|
./configure \
|
|
--build="x86_64-linux-musl" \
|
|
--enable-loadable-sqlite-extensions \
|
|
--enable-optimizations \
|
|
--enable-option-checking=fatal \
|
|
--enable-shared \
|
|
--with-lto \
|
|
--with-system-libmpdec \
|
|
--with-system-expat \
|
|
--without-ensurepip \
|
|
--without-static-libpython && \
|
|
make -j "$(nproc)" \
|
|
LDFLAGS="-Wl,--strip-all" \
|
|
CFLAGS="-fno-semantic-interposition -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-free" \
|
|
EXTRA_CFLAGS="-DTHREAD_STACK_SIZE=0x100000" && \
|
|
make install && \
|
|
find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec scanelf --needed --nobanner --format '%n#p' '{}' ';' \
|
|
| tr ',' '\n' \
|
|
| sort -u \
|
|
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
|
|
| xargs -rt apk add --no-cache && \
|
|
find /usr/local -depth \
|
|
\( \
|
|
-type d -a \( -name test -o -name tests \) \
|
|
\) -exec rm -rf '{}' + && \
|
|
cd /usr/local/bin && \
|
|
ln -s idle3 idle && \
|
|
ln -s pydoc3 pydoc && \
|
|
ln -s python3 python && \
|
|
ln -s python3-config python-config && \
|
|
curl -o \
|
|
/tmp/get-pip.py -L \
|
|
"https://bootstrap.pypa.io/get-pip.py" && \
|
|
/usr/local/bin/python3 /tmp/get-pip.py \
|
|
--disable-pip-version-check \
|
|
--no-cache-dir \
|
|
pip==${HA_PIP_VERSION} && \
|
|
find /usr/local -depth \
|
|
\( \
|
|
-type d -a \( -name test -o -name tests \) \
|
|
\) -exec rm -rf '{}' + ; \
|
|
fi && \
|
|
echo "**** install homeassistant ****" && \
|
|
cd /tmp/core && \
|
|
pip3 install uv==${HA_UV_VERSION} && \
|
|
uv pip install --no-build \
|
|
-r https://raw.githubusercontent.com/home-assistant/docker/${HASS_BASE}/requirements.txt && \
|
|
uv pip install --no-build \
|
|
-r requirements.txt && \
|
|
uv pip install --no-build \
|
|
-r requirements_all.txt \
|
|
isal \
|
|
pycups && \
|
|
uv pip install \
|
|
homeassistant==${HASS_RELEASE} && \
|
|
for cleanfiles in *.pyc *.pyo; do \
|
|
find /usr/local/lib/python3.* -iname "${cleanfiles}" -exec rm -f '{}' + ; \
|
|
done && \
|
|
chown -R root:7310 /usr/local && \
|
|
chmod -R g+w /usr/local && \
|
|
groupadd lsio && \
|
|
groupmod -g 7310 lsio && \
|
|
mv "/usr/local/lib/python${HA_PY_MAJOR}" "/usr/local/lib/python${HA_PY_MAJOR}.bak" && \
|
|
printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version && \
|
|
echo "**** cleanup ****" && \
|
|
apk del --purge \
|
|
build-dependencies && \
|
|
rm -rf \
|
|
/tmp/* \
|
|
/root/.cache \
|
|
/root/.cargo
|
|
|
|
# environment settings. used so pip packages installed by home assistant installs in /config
|
|
ENV HOME="/config"
|
|
|
|
# copy local files
|
|
COPY root/ /
|
|
|
|
# ports and volumes
|
|
EXPOSE 8123
|
|
VOLUME /config
|