├── .dockerignore ├── .gitignore ├── Dockerfile ├── README.md ├── cache.png ├── entrypoint.sh ├── s6 ├── .s6-svscan │ ├── crash │ └── finish ├── apt-cacher-ng │ └── run ├── cron │ └── run └── rsyslogd │ └── run └── util └── prune_hub_tags.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .git 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # rebased/repackaged base image that only updates existing packages 2 | FROM mbentley/debian:bullseye 3 | LABEL maintainer="Matt Bentley " 4 | 5 | RUN apt-get update &&\ 6 | DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y apt-cacher-ng ca-certificates cron logrotate s6 rsyslog &&\ 7 | chown -R apt-cacher-ng:apt-cacher-ng /var/run/apt-cacher-ng &&\ 8 | echo 'PassThroughPattern: ^(.*):443$' >> /etc/apt-cacher-ng/zzz_acng.conf &&\ 9 | echo 'ReuseConnections: 1' >> /etc/apt-cacher-ng/zzz_acng.conf &&\ 10 | sed -i "s#size 10M#size 25M#g" /etc/logrotate.d/apt-cacher-ng &&\ 11 | sed -i '/imklog/s/^/#/' /etc/rsyslog.conf &&\ 12 | rm -rf /var/lib/apt/lists/* 13 | 14 | # add image to use for a lazy health check via image 15 | COPY cache.png /usr/share/doc/apt-cacher-ng/cache.png 16 | 17 | COPY s6 /etc/s6 18 | COPY entrypoint.sh /entrypoint.sh 19 | 20 | VOLUME ["/var/cache/apt-cacher-ng"] 21 | EXPOSE 3142 22 | 23 | ENTRYPOINT ["/entrypoint.sh"] 24 | CMD ["s6-svscan","/etc/s6"] 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mbentley/apt-cacher-ng 2 | 3 | docker image for apt-cacher-ng 4 | based off of debian:bullseye 5 | 6 | To pull this image: 7 | `docker pull mbentley/apt-cacher-ng` 8 | 9 | ## Image Tags 10 | 11 | ### Multi-arch Tags 12 | 13 | The `latest` tag has multi-arch support for `amd64` and `arm64` and will automatically pull the correct tag based on your system's architecture. 14 | 15 | There are also architecture specific tags if you wish to use an explicit architecture tag: 16 | 17 | * `latest-amd64` 18 | * `latest-arm64` 19 | 20 | ### Date Specific Tags 21 | 22 | The `latest` tags also have unique manifests that are generated daily. These are in the format `latest-YYYYMMDD` (e.g. - `latest-20220215`) and can be viewed on [Docker Hub](https://hub.docker.com/repository/docker/mbentley/apt-cacher-ng/tags?page=1&ordering=last_updated&name=latest-20). Each one of these tags will be generated daily and is essentially a point in time snapshot of the `latest` tag's manifest that you can pin to if you wish. Please note that these tags will remain available on Docker Hub for __6 months__ and will not receive security fixes. You will need to update to newer tags as they are published in order to get updated images. If you do not care about specific image digests to pin to, I would suggest just using the `latest` tag. 23 | 24 | ## Example usage 25 | 26 | ``` 27 | docker run -d \ 28 | --name apt-cacher-ng \ 29 | -p 3142:3142 \ 30 | -e TZ="US/Eastern" \ 31 | -v /data/apt-cacher-ng:/var/cache/apt-cacher-ng \ 32 | mbentley/apt-cacher-ng 33 | ``` 34 | 35 | This image runs `apt-cacher-ng`, `cron`, and `rsyslogd` to ensure that apt-cacher-ng functions properly with scheduled jobs and appropriate logging. 36 | 37 | In order to configure a host to make use of apt-cacher-ng on a box, you should create a file on the host `/etc/apt/apt.conf` with the following lines: 38 | 39 | ``` 40 | Acquire::http::Proxy "http://:3142"; 41 | ``` 42 | 43 | You can also bypass the apt caching server on a per client basis by using the following syntax in your `/etc/apt/apt.conf` file: 44 | 45 | ``` 46 | Acquire::HTTP::Proxy:: "DIRECT"; 47 | ``` 48 | 49 | For example: 50 | 51 | ``` 52 | Acquire::HTTP::Proxy::get.docker.com "DIRECT"; 53 | Acquire::HTTP::Proxy::download.virtualbox.org "DIRECT"; 54 | ``` 55 | 56 | Note: The above assumes that you are mapping port 3142 on the docker host and 3142 is accessible from all machines. 57 | 58 | You can also update the /etc/apt-cacher-ng/acng.conf and add one or more `PassThroughPattern` lines to force clients to bypass a repository: 59 | 60 | ``` 61 | PassThroughPattern: get\.docker\.com 62 | PassThroughPattern: download\.virtualbox\.org 63 | ``` 64 | -------------------------------------------------------------------------------- /cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbentley/docker-apt-cacher-ng/20c6ab71faf57379a5db3e9c82f319933ff37e02/cache.png -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # set TZ 4 | export TZ 5 | TZ="${TZ:-US/Eastern}" 6 | 7 | # setting permissions on /var/cache/apt-cacher-ng, /var/log/apt-cacher-ng, and /var/run/apt-cacher-ng 8 | echo -n "INFO: Setting permissions on /var/cache/apt-cacher-ng, /var/log/apt-cacher-ng, and /var/run/apt-cacher-ng..." 9 | chown -R apt-cacher-ng:apt-cacher-ng /var/cache/apt-cacher-ng /var/log/apt-cacher-ng /var/run/apt-cacher-ng 10 | echo -e "done" 11 | 12 | # run CMD 13 | echo "INFO: entrypoint complete; executing CMD '${*}'" 14 | exec "${@}" 15 | -------------------------------------------------------------------------------- /s6/.s6-svscan/crash: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Executing .s6-svscan/crash with arguments ${*}" 4 | -------------------------------------------------------------------------------- /s6/.s6-svscan/finish: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # do nothing 4 | echo "Executing .s6-svscan/finish with arguments ${*}" 5 | -------------------------------------------------------------------------------- /s6/apt-cacher-ng/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec /usr/sbin/apt-cacher-ng -c /etc/apt-cacher-ng SocketPath=/var/run/apt-cacher-ng/socket pidfile=/var/run/apt-cacher-ng/pid foreground=1 4 | -------------------------------------------------------------------------------- /s6/cron/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec /usr/sbin/cron -f -L 15 4 | -------------------------------------------------------------------------------- /s6/rsyslogd/run: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | exec /usr/sbin/rsyslogd -n -iNONE 4 | -------------------------------------------------------------------------------- /util/prune_hub_tags.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # set namespace & repository name 4 | IMAGE_REPO="mbentley/apt-cacher-ng" 5 | 6 | # get the date, in seconds, for when we should purge tags before 7 | PURGE_DATE="$(date --date='-6 months' +%s)" 8 | 9 | # get Docker Hub credentials 10 | HUB_AUTH="$(jq -r '.auths."https://index.docker.io/v1/".auth' "${HOME}/.docker/config.json" | base64 -d)" 11 | 12 | # make sure we received credentials 13 | if [ -z "${HUB_AUTH}" ] 14 | then 15 | echo "ERROR: authorization data not found (have you performed a \"docker login\")?" 16 | exit 1 17 | else 18 | # get a token 19 | TOKEN=$(curl -s -H "Content-Type: application/json" -X POST -d '{"username": "'"$(echo "${HUB_AUTH}" | awk -F ':' '{print $1}')"'", "password": "'"$(echo "${HUB_AUTH}" | awk -F ':' '{print $2}')"'"}' https://hub.docker.com/v2/users/login/ | jq -r .token) 20 | fi 21 | 22 | # make sure we received a docker hub token 23 | if [ -z "${TOKEN}" ] 24 | then 25 | echo "ERROR: failed to get a Docker Hub auth token" 26 | exit 1 27 | fi 28 | 29 | # initialize default loop variables 30 | TAG_PAGE="1" 31 | NEXT_PAGE="" 32 | 33 | while [ "${NEXT_PAGE}" != "null" ] 34 | do 35 | # get a page of tags 36 | PAGE_OF_TAGS="$(curl -s -H "Authorization: JWT ${TOKEN}" "https://hub.docker.com/v2/repositories/${IMAGE_REPO}/tags?page=${TAG_PAGE}&page_size=50")" 37 | 38 | # set the next page variable 39 | NEXT_PAGE="$(echo "${PAGE_OF_TAGS}" | jq -r .next)" 40 | 41 | # add the tags from the page to the list of tags 42 | HUB_TAGS="${HUB_TAGS} 43 | $(echo "${PAGE_OF_TAGS}" | jq -r '.results[] | .name + " " + .tag_last_pushed')" 44 | 45 | # increment the tag page 46 | TAG_PAGE=$((TAG_PAGE+1)) 47 | done 48 | 49 | # trim off any blank lines from the list of tags 50 | HUB_TAGS="$(echo "${HUB_TAGS}" | sed '/^[[:space:]]*$/d')" 51 | 52 | while read -r TAG_NAME TAG_LAST_PUSHED 53 | do 54 | # check to see if we should skip the tag 55 | if echo "${TAG_NAME}" | grep -qE '(^latest$)|(-arm64$)|(-amd64$)|(-armv7l$)' 56 | then 57 | echo "skip tag ${TAG_NAME}" 58 | else 59 | # convert the date to seconds 60 | TAG_LAST_PUSHED=$(date -d "${TAG_LAST_PUSHED}" +%s) 61 | 62 | # compare the tag last pushed date to the purge date cutoff 63 | if [ "${TAG_LAST_PUSHED}" -lt "${PURGE_DATE}" ] 64 | then 65 | # purge tag 66 | echo "tag age $(date -d "@${TAG_LAST_PUSHED}" +%Y-%m-%d), threshold $(date -d "@${PURGE_DATE}" +%Y-%m-%d), ${TAG_NAME}, removing" 67 | 68 | # delete the tag 69 | curl -s -H "Authorization: JWT ${TOKEN}" -X DELETE "https://hub.docker.com/v2/repositories/${IMAGE_REPO}/tags/${TAG_NAME}/" 70 | else 71 | # do not purge tag 72 | echo "tag age $(date -d "@${TAG_LAST_PUSHED}" +%Y-%m-%d), threshold $(date -d "@${PURGE_DATE}" +%Y-%m-%d), ${TAG_NAME}, NOT removing" 73 | fi 74 | fi 75 | done < <(echo "${HUB_TAGS}") 76 | --------------------------------------------------------------------------------