Skip to content

Commit

Permalink
feat: rewrite Dockerfiles and update README.md for efficiency
Browse files Browse the repository at this point in the history
- Removed the compress stage from Dockerfile and instead utilized a pre-compressed ffmpeg package from ghcr.io repository.
- Updated various Dockerfiles to use yt-dlp version 2024.04.09 from the previous version.
- Switched all Dockerfiles to `ghcr.io/jim60105/static-ffmpeg-upx:7.0-1` for `ffmpeg`, `ffprobe`, and `dumb-init`, previously it used `mwader/static-ffmpeg`.
- Reordered some sections in `README.md`.
- Added image description and metadata labels to Dockerfiles.
- In Dockerfiles, added more cleanup steps after installing packages using pip to reduce the image size.
- Changed directory permissions in Dockerfiles and added `/licenses` for license files.
- In Dockerfiles, replaced binary files effective permissions to 775 from 774.

Signed-off-by: 陳鈞 <[email protected]>
  • Loading branch information
jim60105 committed May 5, 2024
1 parent 6ac7ebc commit 3517c13
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 94 deletions.
32 changes: 3 additions & 29 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,6 @@ ARG UID=1001
ARG VERSION=EDGE
ARG RELEASE=0

########################################
# Compress stage
########################################
FROM alpine:3 as compress

# RUN mount cache for multi-arch: https://github.com/docker/buildx/issues/549#issuecomment-1788297892
ARG TARGETARCH
ARG TARGETVARIANT

# Compress ffmpeg and ffprobe
# UPX skip small files: https://github.com/upx/upx/blob/5bef96806860382395d9681f3b0c69e0f7e853cf/src/p_unix.cpp#L80
# UPX skip large files: https://github.com/upx/upx/blob/b0dc48316516d236664dfc5f1eb5f2de00fc0799/src/conf.h#L134
RUN --mount=type=cache,id=apk-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apk \
--mount=from=mwader/static-ffmpeg:7.0-1,source=/ffmpeg,target=/tmp/ffmpeg,rw \
--mount=from=mwader/static-ffmpeg:7.0-1,source=/ffprobe,target=/tmp/ffprobe,rw \
apk update && apk add -u \
-X "https://dl-cdn.alpinelinux.org/alpine/edge/community" \
# Use upx to compress the ffmpeg binary
upx dumb-init && \
cp /tmp/ffmpeg / && \
cp /tmp/ffprobe / && \
upx --best --lzma /ffmpeg || true; \
upx --best --lzma /ffprobe || true; \
upx --best --lzma /usr/bin/dumb-init || true; \
apk del upx

########################################
# Final stage
########################################
Expand All @@ -51,9 +25,9 @@ COPY --link --chown=$UID:0 --chmod=775 LICENSE /licenses/Dockerfile.LICENSE
COPY --link --chown=$UID:0 --chmod=775 yt-dlp/LICENSE /licenses/yt-dlp.LICENSE

RUN --mount=type=cache,id=apk-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apk \
--mount=from=compress,source=/ffmpeg,target=/ffmpeg,rw \
--mount=from=compress,source=/ffprobe,target=/ffprobe,rw \
--mount=from=compress,source=/usr/bin/dumb-init,target=/dumb-init,rw \
--mount=from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1,source=/ffmpeg,target=/ffmpeg,rw \
--mount=from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1,source=/ffprobe,target=/ffprobe,rw \
--mount=from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1,source=/dumb-init,target=/dumb-init,rw \
apk update && apk add -u \
# These branches follows the yt-dlp release
-X "https://dl-cdn.alpinelinux.org/alpine/edge/main" \
Expand Down
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,11 @@ It is important to note that the [Dockerfile](Dockerfile) always builds with [th

> [!NOTE]
>
> - The apk edge branch follows the latest release of yt-dlp.
> - The `alpine.Dockerfile` installs yt-dlp from pip source, so the image size may slightly different compared to the `Dockerfile` even when they have the same version.
> - The apk edge branch follows the latest release of yt-dlp.
> - The `alpine.Dockerfile` installs yt-dlp from pip source, so the image size may slightly different compared to the `Dockerfile` even when they have the same version.
### Build Command

> [!NOTE]
> If you are using an earlier version of the docker client, it is necessary to [enable the BuildKit mode](https://docs.docker.com/build/buildkit/#getting-started) when building the image. This is because I used the `COPY --link` feature which enhances the build performance and was introduced in Buildx v0.8.
> With the Docker Engine 23.0 and Docker Desktop 4.19, Buildx has become the default build client. So you won't have to worry about this when using the latest version.
```bash
docker build -t yt-dlp .
docker build --build-arg BUILD_VERSION=2023.12.30 -f ./alpine.Dockerfile -t yt-dlp:alpine .
Expand All @@ -59,24 +55,17 @@ docker build --build-arg BUILD_VERSION=2023.12.30 -f ./distroless.Dockerfile -t
> [!TIP]
> I've notice that that both the UBI version and the Distroless version offer no advantages over the Alpine version. So _**please use the Alpine version**_ unless you have specific reasons not to. All of these base images are great, some of them were simply not that suitable for our project.
> [!NOTE]
> If you are using an earlier version of the docker client, it is necessary to [enable the BuildKit mode](https://docs.docker.com/build/buildkit/#getting-started) when building the image. This is because I used the `COPY --link` feature which enhances the build performance and was introduced in Buildx v0.8.
> With the Docker Engine 23.0 and Docker Desktop 4.19, Buildx has become the default build client. So you won't have to worry about this when using the latest version.
## LICENSE

> [!NOTE]
> The main program, [yt-dlp/yt-dlp](https://github.com/yt-dlp/yt-dlp), is distributed under [Unlicense license](https://github.com/yt-dlp/yt-dlp/blob/master/LICENSE).
> Please consult their repository for access to the source code and licenses.
> The following is the license for the Dockerfiles and CI workflows in this repository.
> [!CAUTION]
> A GPLv3 licensed Dockerfile means that you _**MUST**_ **distribute the source code with the same license**, if you
>
> - Re-distribute the image. (You can simply point to this GitHub repository if you doesn't made any code changes.)
> - Distribute a image that uses code from this repository.
> - Or **distribute a image based on this image**. (`FROM ghcr.io/jim60105/yt-dlp` in your Dockerfile)
>
> "Distribute" means to make the image available for other people to download, usually by pushing it to a public registry. If you are solely using it for your personal purposes, this has no impact on you.
>
> Please consult the [LICENSE](LICENSE) for more details.
<img src="https://github.com/jim60105/docker-yt-dlp/assets/16995691/f33f8175-af23-4a8a-ad69-efd17a7625f4" alt="gplv3" width="300" />

[GNU GENERAL PUBLIC LICENSE Version 3](LICENSE)
Expand All @@ -86,3 +75,14 @@ This program is free software: you can redistribute it and/or modify it under th
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.

> [!CAUTION]
> A GPLv3 licensed Dockerfile means that you _**MUST**_ **distribute the source code with the same license**, if you
>
> - Re-distribute the image. (You can simply point to this GitHub repository if you doesn't made any code changes.)
> - Distribute a image that uses code from this repository.
> - Or **distribute a image based on this image**. (`FROM ghcr.io/jim60105/yt-dlp` in your Dockerfile)
>
> "Distribute" means to make the image available for other people to download, usually by pushing it to a public registry. If you are solely using it for your personal purposes, this has no impact on you.
>
> Please consult the [LICENSE](LICENSE) for more details.
72 changes: 53 additions & 19 deletions alpine.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,60 +1,94 @@
# syntax=docker/dockerfile:1
ARG UID=1001
ARG BUILD_VERSION=2023.12.30
ARG VERSION=2024.04.09
ARG RELEASE=0

########################################
# Build stage
########################################
FROM python:3.12-alpine as build

# RUN mount cache for multi-arch: https://github.com/docker/buildx/issues/549#issuecomment-1788297892
ARG TARGETARCH
ARG TARGETVARIANT

ARG BUILD_VERSION

WORKDIR /app

# Install under /root/.local
ENV PIP_USER="true"
ARG PIP_NO_WARN_SCRIPT_LOCATION=0
ARG PIP_ROOT_USER_ACTION="ignore"
ARG PIP_NO_COMPILE="true"
ARG PIP_DISABLE_PIP_VERSION_CHECK="true"

ARG VERSION
RUN --mount=type=cache,id=pip-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/pip \
pip3.12 install yt-dlp==$BUILD_VERSION && \
pip3.12 install -U --force-reinstall pip setuptools wheel && \
pip3.12 install yt-dlp==$VERSION && \
# Cleanup
find "/root/.local" -name '*.pyc' -print0 | xargs -0 rm -f || true ; \
find "/root/.local" -type d -name '__pycache__' -print0 | xargs -0 rm -rf || true ;

########################################
# Final stage
########################################
FROM python:3.12-alpine as final

ARG UID

RUN pip3.12 uninstall -y setuptools pip wheel && \
rm -rf /root/.cache/pip

# Use dumb-init to handle signals
RUN apk add -u --no-cache dumb-init
# Create user
ARG UID
RUN adduser -H -g "" -D $UID -u $UID -G root

# ffmpeg (6.1 is broken, so override it)
COPY --link --from=mwader/static-ffmpeg:6.1.1 /ffmpeg /usr/bin/
COPY --link --from=mwader/static-ffmpeg:6.1.1 /ffprobe /usr/bin/
# Create directories with correct permissions
RUN install -d -m 775 -o $UID -g 0 /download && \
install -d -m 775 -o $UID -g 0 /licenses

# Create user
RUN addgroup -g $UID $UID && \
adduser -g "" -D $UID -u $UID -G $UID
# ffmpeg
COPY --link --from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1 /ffmpeg /usr/bin/
COPY --link --from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1 /ffprobe /usr/bin/

# dumb-init
COPY --link --from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1 /dumb-init /usr/bin/

# Copy licenses (OpenShift Policy)
COPY --link --chown=$UID:0 --chmod=775 LICENSE /licenses/Dockerfile.LICENSE
COPY --link --chown=$UID:0 --chmod=775 yt-dlp/LICENSE /licenses/yt-dlp.LICENSE

# Copy dist and support arbitrary user ids (OpenShift best practice)
# https://docs.openshift.com/container-platform/4.14/openshift_images/create-images.html#use-uid_create-images
COPY --chown=$UID:0 --chmod=774 \
--from=build /root/.local /home/$UID/.local
COPY --link --chown=$UID:0 --chmod=775 --from=build /root/.local /home/$UID/.local

ENV PATH="/home/$UID/.local/bin:$PATH"

# Remove these to prevent the container from executing arbitrary commands
RUN rm /bin/echo /bin/ln /bin/rm /bin/sh

# Run as non-root user
USER $UID
WORKDIR /download

VOLUME [ "/download" ]

USER $UID

STOPSIGNAL SIGINT

# Use dumb-init as PID 1 to handle signals properly
ENTRYPOINT [ "dumb-init", "--", "yt-dlp", "--no-cache-dir" ]
CMD ["--help"]
CMD ["--help"]

ARG VERSION
ARG RELEASE
LABEL name="jim60105/docker-yt-dlp" \
# Authors for yt-dlp
vendor="yt-dlp" \
# Maintainer for this docker image
maintainer="jim60105" \
# Dockerfile source repository
url="https://github.com/jim60105/docker-yt-dlp" \
version=${VERSION} \
# This should be a number, incremented with each change
release=${RELEASE} \
io.k8s.display-name="yt-dlp" \
summary="yt-dlp: A feature-rich command-line audio/video downloader." \
description="yt-dlp is a feature-rich command-line audio/video downloader with support for thousands of sites. The project is a fork of youtube-dl based on the now inactive youtube-dlc. For more information about this tool, please visit the following website: https://github.com/yt-dlp/yt-dlp"
65 changes: 55 additions & 10 deletions distroless.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,43 +1,88 @@
# syntax=docker/dockerfile:1
ARG BUILD_VERSION=2023.12.30
ARG VERSION=2024.04.09
ARG RELEASE=0

########################################
# Build stage
########################################
FROM python:3.12-bookworm as build

# RUN mount cache for multi-arch: https://github.com/docker/buildx/issues/549#issuecomment-1788297892
ARG TARGETARCH
ARG TARGETVARIANT

ARG BUILD_VERSION

WORKDIR /app

# Install under /root/.local
ENV PIP_USER="true"
ARG PIP_NO_WARN_SCRIPT_LOCATION=0
ARG PIP_ROOT_USER_ACTION="ignore"
ARG PIP_NO_COMPILE="true"
ARG PIP_DISABLE_PIP_VERSION_CHECK="true"

ARG VERSION
RUN --mount=type=cache,id=pip-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/pip \
pip3.12 install dumb-init yt-dlp==$BUILD_VERSION && \
pip install -U --force-reinstall pip setuptools wheel && \
pip install yt-dlp==$VERSION && \
# Cleanup
find "/root/.local" -name '*.pyc' -print0 | xargs -0 rm -f || true ; \
find "/root/.local" -type d -name '__pycache__' -print0 | xargs -0 rm -rf || true ;
find "/root/.local" -type d -name '__pycache__' -print0 | xargs -0 rm -rf || true ; \
# Make an empty directory for final stage
mkdir -p /newdir

########################################
# Final stage
# Distroless image use monty(1000) for non-root user
########################################
FROM al3xos/python-distroless:3.12-debian12 as final

ARG UID=1000

# Create directories with correct permissions
COPY --link --chown=$UID:0 --chmod=775 --from=build /newdir /download
COPY --link --chown=$UID:0 --chmod=775 --from=build /newdir /licenses

# ffmpeg
COPY --link --from=mwader/static-ffmpeg:6.1.1 /ffmpeg /usr/bin/
COPY --link --from=mwader/static-ffmpeg:6.1.1 /ffprobe /usr/bin/
COPY --link --from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1 /ffmpeg /usr/bin/
COPY --link --from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1 /ffprobe /usr/bin/

# dumb-init
COPY --link --from=ghcr.io/jim60105/static-ffmpeg-upx:7.0-1 /dumb-init /usr/bin/

# Copy licenses (OpenShift Policy)
COPY --link --chown=$UID:0 --chmod=775 LICENSE /licenses/Dockerfile.LICENSE
COPY --link --chown=$UID:0 --chmod=775 yt-dlp/LICENSE /licenses/yt-dlp.LICENSE

# Copy dist and support arbitrary user ids (OpenShift best practice)
# https://docs.openshift.com/container-platform/4.14/openshift_images/create-images.html#use-uid_create-images
COPY --chown=1000:0 --chmod=774 \
--from=build /root/.local /home/monty/.local
COPY --link --chown=$UID:0 --chmod=775 --from=build /root/.local /home/monty/.local

ENV PATH="/home/monty/.local/bin:$PATH"

WORKDIR /download

VOLUME [ "/download" ]

USER $UID

STOPSIGNAL SIGINT

# Use dumb-init as PID 1 to handle signals properly
ENTRYPOINT [ "dumb-init", "--", "yt-dlp", "--no-cache-dir" ]
CMD ["--help"]
CMD ["--help"]

ARG VERSION
ARG RELEASE
LABEL name="jim60105/docker-yt-dlp" \
# Authors for yt-dlp
vendor="yt-dlp" \
# Maintainer for this docker image
maintainer="jim60105" \
# Dockerfile source repository
url="https://github.com/jim60105/docker-yt-dlp" \
version=${VERSION} \
# This should be a number, incremented with each change
release=${RELEASE} \
io.k8s.display-name="yt-dlp" \
summary="yt-dlp: A feature-rich command-line audio/video downloader." \
description="yt-dlp is a feature-rich command-line audio/video downloader with support for thousands of sites. The project is a fork of youtube-dl based on the now inactive youtube-dlc. For more information about this tool, please visit the following website: https://github.com/yt-dlp/yt-dlp"
Loading

0 comments on commit 3517c13

Please sign in to comment.