如何在构建时在 Docker 容器中设置时间

How to set time in Docker container at build time

所以我正在尝试构建一个 Alpine 容器,包括一个需要 bashcurl 才能安装的应用程序。

问题是 Alpine 似乎认为年份是 2037(可能是因为主机 Pi 缺少硬件时钟)忽略了正确的主机 OS/system 时间(由 NTP 保持最新),所以apk 调用失败:

fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/armv7/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/armv7/APKINDEX.tar.gz
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.14/main: temporary error (try again later)
WARNING: Ignoring https://dl-cdn.alpinelinux.org/alpine/v3.14/community: temporary error (try again later)
ERROR: unable to select packages:
  bash (no such package):
    required by: world[bash]
  curl (no such package):
    required by: world[curl]

可以使用 docker run -it --privileged ... 以交互模式启动容器,时间将被正确设置,因此安装顺利进行。 我发现的参考表明 privileged 构建是不可能的(参考?)。

我尝试了很多方法在构建时将时间传递到容器中,但都没有成功:

# syntax=docker/dockerfile:1
FROM alpine:3.14
# Pass build-time using `--build-arg time=$(date +%s)` (w/ default value)
ARG time=1632511895
#RUN ["/bin/date", "-s", "@$time"]      # `invalid date @$time`
#RUN ["/bin/date", "-s", "@"$time]      # `/bin/date/` not found
#RUN echo $(date)       # no output
#RUN date -s @$time     # `date: can't set date: Operation not permitted`
#RUN sudo date -s @$time        # /bin/sh: sudo: not found

# cannot build with `--privileged` so clock will be in 2037 and apk will fail
RUN apk add --no-cache curl bash
WORKDIR /tmp

如何在构建时安装 curlbash

尝试次数

更多信息

# date       
Sat Oct 23 13:17:47 EDT 2021

# docker info
    Client:
     Debug Mode: false
    
    Server:
     Containers: 4
      Running: 0
      Paused: 0
      Stopped: 4
     Images: 19
     Server Version: 19.03.15
     Storage Driver: overlay2
      Backing Filesystem: extfs
      Supports d_type: true
      Native Overlay Diff: true
     Logging Driver: json-file
     Cgroup Driver: cgroupfs
     Plugins:
      Volume: local
      Network: bridge host ipvlan macvlan null overlay
      Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
     Swarm: inactive
     Runtimes: runc
     Default Runtime: runc
     Init Binary: docker-init
     containerd version: 269548fa27e0089a8b8278fc4fc781d7f65a939b
     runc version: ff819c7e9184c13b7c2607fe6c30ae19403a7aff
     init version: fec3683
     Security Options:
      seccomp
       Profile: default
     Kernel Version: 4.19.66-v7+
     Operating System: Raspbian GNU/Linux 9 (stretch)
     OSType: linux
     Architecture: armv7l
     CPUs: 4
     Total Memory: 858.7MiB
     Name: rpi0.crcondo
     ID: WW63:IXLY:OBPE:AX4O:45H7:OAUH:CELE:ALDG:ZHC3:RTQW:I32M:GSDL
     Docker Root Dir: /var/lib/docker
     Debug Mode: false
     Registry: https://index.docker.io/v1/
     Labels:
     Experimental: false
     Insecure Registries:
      127.0.0.0/8
     Live Restore Enabled: false
    
    WARNING: No swap limit support
    WARNING: No cpu cfs quota support
    WARNING: No cpu cfs period support

我会回答“如何在构建时安装 curl 和 bash”而不是“如何在构建时在 Docker 容器中设置时间”:

我猜 apk 失败是因为 repo TLS 证书 dl-cdn.alpinelinux.org 在 2037 之后无效 = 可以创建有效的 TLS 连接。您只需要安装包,因此在这种情况下您可能会牺牲 TLS 安全性,并且可以使用与存储库的纯 HTTP 连接作为解决方法。例如

RUN \
  sed -i 's/https/http/g' /etc/apk/repositories && \
  apk add --no-cache curl bash

很遗憾,apk doesn't have any flag to ignore TLS verification,因此目前只能使用此解决方法。

顺便说一句:我会尝试在主机 Pi 上使用良好的旧 NTP。容器使用主机时间,因此主机级别的正确时间配置(通过 NTP 同步)应该也可以解决容器级别的问题(然后还有 TLS 证书验证问题)。


更新:

https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.14.0:

所以你需要升级你的Docker版本(20.10.0+),你只有19.03.15.

所以@JanGaraj 的回答给了我一个重要的线索:Alpine 3.14's release notes 提到它需要 Docker >=20.10.0(我目前在 19.03.15)。

回到Alpine 3.13's release notes

  • Docker 版本要求是 19.03.9 [我有]
  • 连同libseccomp 2.4.2

仅使用 FROM alpine:3.13 仍然无效。

检查第二个要求,我有一个以前版本的 libseccomp[2],网络搜索让我找到这个 post:https://blog.samcater.com/fix-workaround-rpi4-docker-libseccomp2-docker-20/

使用其中的步骤升级 libseccomp[2] alpine:3.13alpine:3.14!!

都有效

修复步骤(来自post)

The steps for libseccomp2 are well documented, as this has been a problem on multiple platforms (not just RPI4). You could do a 'oneshot' installation of a newer version, which can be found here https://github.com/itzg/docker-minecraft-server/issues/755#issuecomment-781615497

Personally I feel the better method is to install it from the Buster Backports repo, which is very safe to add. It also means any future updates to libseccomp will be applied to the Pi.

# Get signing keys to verify the new packages, otherwise they will not install
rpi ~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC 648ACFD622F3D138

# Add the Buster backport repository to apt sources.list
rpi ~$ echo 'deb http://httpredir.debian.org/debian buster-backports main contrib non-free' | sudo tee -a /etc/apt/sources.list.d/debian-backports.list

rpi ~$ sudo apt update
rpi ~$ sudo apt install libseccomp2 -t buster-backports

现在进入下一个构建时错误消息