La commande «date -d» échoue sur le conteneur Docker Alpine Linux

9

J'ai construit Alpine Linux dans un conteneur Docker avec le Dockerfile suivant:

FROM alpine:3.2
RUN apk add --update jq curl && rm -rf /var/cache/apk/*

le build s'est déroulé avec succès:

$ docker build -t collector .
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon 
Step 0 : FROM alpine:3.2
3.2: Pulling from alpine
8697b6cc1f48: Already exists 
alpine:3.2: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:eb84cc74347e4d7c484d566dec8a5eef82bab1b78308b92cda559bcff29c27cc
Status: Downloaded newer image for alpine:3.2
 ---> 8697b6cc1f48
Step 1 : RUN apk add --update jq curl && rm -rf /var/cache/apk/*
 ---> Running in 888571296e79
fetch http://dl-4.alpinelinux.org/alpine/v3.2/main/x86_64/APKINDEX.tar.gz
(1/11) Installing run-parts (4.4-r0)
(2/11) Installing openssl (1.0.2a-r1)
(3/11) Installing lua5.2-libs (5.2.4-r0)
(4/11) Installing lua5.2 (5.2.4-r0)
(5/11) Installing ncurses-terminfo-base (5.9-r3)
(6/11) Installing ncurses-widec-libs (5.9-r3)
(7/11) Installing lua5.2-posix (33.3.1-r2)
(8/11) Installing ca-certificates (20141019-r2)
(9/11) Installing libssh2 (1.5.0-r0)
(10/11) Installing curl (7.42.1-r0)
(11/11) Installing jq (1.4-r0)
Executing busybox-1.23.2-r0.trigger
Executing ca-certificates-20141019-r2.trigger
OK: 9 MiB in 26 packages
 ---> 7625779b773d
Removing intermediate container 888571296e79
Successfully built 7625779b773d

de toute façon quand je l'exécute, date -dil échoue:

$ docker run -i -t collector sh
/ # date -d yesterday
date: invalid date 'yesterday'
/ # date -d now
date: invalid date 'now'
/ # date -d next-month
date: invalid date 'next-month'

tandis que le reste des options semblent fonctionner correctement:

/ # date 
Sat May 30 18:57:24 UTC 2015
/ # date +"%A"
Saturday
/ # date +"%Y-%m-%dT%H:%M:%SZ"
2015-05-30T19:00:38Z
BBJ3
la source
Ne comptez pas sur la datecommande qui prend en charge les dates de référence avec "maintenant", "hier", etc., ou d'autres extensions non standard.
Janis

Réponses:

26

La version BusyBox / Alpine de la date ne prend pas en charge les -doptions, même si l'aide est exactement la même dans la version Ubuntu ainsi que dans d'autres distributions plus grasses.

De plus, la "conteneurisation" ne manque rien ici.

Pour travailler avec des -doptions, il vous suffit d'ajouter un coreutilspackage:

$ cat Dockerfile.alpine-coreutils
FROM alpine:3.2
RUN apk add --update coreutils && rm -rf /var/cache/apk/*


$ docker build -t alpine-coreutils - <  Dockerfile.alpine-coreutils
Sending build context to Docker daemon 2.048 kB
Sending build context to Docker daemon 
Step 0 : FROM alpine:3.2
3.2: Pulling from alpine
8697b6cc1f48: Already exists 
alpine:3.2: The image you are pulling has been verified. Important: image verification is a tech preview feature and should not be relied on to provide security.
Digest: sha256:eb84cc74347e4d7c484d566dec8a5eef82bab1b78308b92cda559bcff29c27cc
Status: Downloaded newer image for alpine:3.2
 ---> 8697b6cc1f48
Step 1 : RUN apk add --update coreutils && rm -rf /var/cache/apk/*
 ---> Running in 694fa5cb271c
fetch http://dl-4.alpinelinux.org/alpine/v3.2/main/x86_64/APKINDEX.tar.gz
(1/3) Installing libattr (2.4.47-r3)
(2/3) Installing libacl (2.2.52-r2)
(3/3) Installing coreutils (8.23-r0)
Executing busybox-1.23.2-r0.trigger
OK: 12 MiB in 18 packages
 ---> a7d9116a00ee
Removing intermediate container 694fa5cb271c
Successfully built a7d9116a00ee


$ docker run -i -t alpine-coreutils sh
/ # date -d last-week
Sun May 24 09:19:34 UTC 2015
/ # date -d yesterday 
Sat May 30 09:19:46 UTC 2015
/ # date 
Sun May 31 09:19:50 UTC 2015

La taille de l'image va doubler mais est jusqu'à 11,47 Mo, plus d'un ordre de moins, par rapport au standard Debian:

$ docker images
REPOSITORY                 TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
alpine-coreutils           latest              a7d9116a00ee        2 minutes ago       11.47 MB
alpine                     3.2                 8697b6cc1f48        2 days ago          5.242 MB
debian                     latest              df2a0347c9d0        11 days ago         125.2 MB

Merci à Andy Shinn: https://github.com/gliderlabs/docker-alpine/issues/40#issuecomment-107122371

Et à Christopher Horrell: https://github.com/docker-library/official-images/issues/771#issuecomment-107101595

BBJ3
la source
1

Je suppose que le que datevous pouvez exécuter dans ce conteneur n'est pas la date de coreutils GNU qui est couramment disponible sur les hôtes Linux, mais l'une des applets Busybox . Essayez d'obtenir des messages d'aide des deux.

# date --help
BusyBox v1.22.1 (Ubuntu 1:1.22.0-9ubuntu1) multi-call binary.

Usage: date [OPTIONS] [+FMT] [TIME]

Display time (using +FMT), or set time

    [-s,--set] TIME Set time to TIME
    -u,--utc    Work in UTC (don't convert to local time)
    -R,--rfc-2822   Output RFC-2822 compliant date string
    -I[SPEC]    Output ISO-8601 compliant date string
            SPEC='date' (default) for date only,
            'hours', 'minutes', or 'seconds' for date and
            time to the indicated precision
    -r,--reference FILE Display last modification time of FILE
    -d,--date TIME  Display TIME, not 'now'
    -D FMT      Use FMT for -d TIME conversion

Recognized TIME formats:
    hh:mm[:ss]
    [YYYY.]MM.DD-hh:mm[:ss]
    YYYY-MM-DD hh:mm[:ss]
    [[[[[YY]YY]MM]DD]hh]mm[.ss]
    'date TIME' form accepts MMDDhhmm[[YY]YY][.ss] instead

BusyBox propose de nombreuses applets pour les commandes standard Posix avec un seul binaire croqué, mais la plupart d'entre elles ont des fonctions très restreintes en échange de sa taille enregistrée (comparer les sorties de find --helpou tar --helpdans les deux environnements par exemple). Il arrive fréquemment qu'un script qui s'exécute correctement dans l'environnement de développement / hôte ne fonctionne pas du tout dans l'environnement de conteneur / cible avec BusyBox.

yaegashi
la source
1

busybox dateprend en charge une -Doption que (comme zshl « strftimemais contrairement à GNU date) vous donne une interface à strptime()laquelle vous pouvez analyser les dates (mais pas de dates relatives) dans tout format (ast ouvert dateet ksh93» s printfont aussi des façons de personnaliser le format d'entrée).

busyboxest construit par rapport à une implémentation de bibliothèque C dont strptime()et strftime()prenant en charge l' %sindicateur non standard , vous pouvez faire:

date -D %s -d "$(($(date +%s) - 86400))"

Dans la bibliothèque musl C que Linux alpin utilise cependant, strftime()prend en charge %smais strptime()ne le fait pas. C'est OK mais comme busybox date, comme GNU dateprend en charge la @epochtimespécification de date, vous pouvez donc faire:

date -d "@$(($(date +%s) - 86400))"

Ce qui vous donnera la date il y a 86400 secondes, sans l'ambiguïté de GNU datede yesterday(est - il y a 86400, ou est - ce hier au même moment de la journée? Et s'il n'y avait pas de temps de la journée d' hier parce que l'horloge a changé pour DST?).

Cette syntaxe devrait également fonctionner avec GNU date.

Avec ast-open date(ou ksh93 printf '%(%c)T'), vous utiliseriez:

date -d "#$(($(date +%s) - 86400))"

au lieu.

Notez que si vous souhaitez signaler l'heure UTC (Zulu), vous devez utiliser TZ=UTC0 dateou date -uautrement, vous obtiendrez l'heure dans le fuseau horaire du système / de l'utilisateur.

Stéphane Chazelas
la source