Как сбросить «ENV» в dockerfile? - PullRequest
       21

Как сбросить «ENV» в dockerfile?

2 голосов
/ 22 апреля 2019

По некоторым причинам я должен установить "http_proxy" и "https_proxy" ENV в моем файле Docker.Я хотел бы теперь сбросить их, потому что есть также некоторый процесс строительства, который не может быть сделан через прокси.

# dockerfile

# ... some process

ENV http_proxy=http://...
ENV https_proxy=http://...

# ... some process that needs the proxy to finish

UNSET ENV http_proxy # how to I unset the proxy ENV here?
UNSET ENV https_proxy

# ... some process that can't use the proxy 

Ответы [ 4 ]

1 голос
/ 24 июля 2019

Зависит от того, какого эффекта вы пытаетесь достичь.

Обратите внимание, что с точки зрения прагматики (то есть того, как на самом деле говорят разработчики), «сброс переменной» может означать две вещи: удаление ее из среды или установка переменной в пустое значение. Технически это две разные операции. На практике, однако, я не сталкивался со случаем, когда программное обеспечение, которым я пытаюсь управлять, различает переменную, отсутствующую в среде, и переменную, присутствующую в среде, но имеющую пустое значение. Я обычно могу использовать любой метод, чтобы получить тот же результат.

Если вам все равно, находится ли переменная в слоях, созданных Docker, но если оставить ее с непустым значением, возникнут проблемы на последующих этапах сборки.

В этом случае вы можете использовать ENV VAR_NAME= в той точке вашего Dockerfile, из которой вы хотите сбросить переменную. Синтаксическое примечание: Docker допускает два синтаксиса для ENV: этот ENV VAR=1 совпадает с ENV VAR 1. Вы можете отделить имя переменной от значения пробелом или знаком равенства. Если вы хотите «сбросить» переменную, установив для нее пустое значение, вы должны использовать синтаксис знака равенства, иначе вы получите ошибку во время сборки.

Так, например, вы можете сделать это:

ENV NOT_SENSITIVE some_value
RUN something

ENV NOT_SENSITIVE=
RUN something_else

Когда something работает, NOT_SENSITIVE устанавливается на some_value. Когда something_else выполняется, NOT_SENSITIVE устанавливается в пустую строку.

Важно отметить, что выполнение unset NOT_SENSITIVE в качестве команды оболочки не будет влиять на что-либо еще, кроме того, что выполняется в этой оболочке. Вот пример:

ENV NOT_SENSITIVE some_value
RUN unset NOT_SENSITIVE && printenv NOT_SENSITIVE || echo "does not exist"

RUN printenv NOT_SENSITIVE

Первый RUN напечатает does not exist, потому что NOT_SENSITIVE сбрасывается при выполнении printenv и потому что он не установлен printenv возвращает ненулевой код выхода, который вызывает выполнение echo. На второй RUN не влияет unset в первом RUN. Он выведет some_value на экран.

Но что, если мне нужно удалить переменную из среды, а не просто установить ее в пустое значение?

В этом случае использование ENV VAR_NAME= не будет работать. Я не знаю, как сказать Docker: «С этого момента вы должны удалить эту переменную из среды, а не просто установить для нее пустое значение».

Если вы все еще хотите использовать ENV для установки вашей переменной, вам придется начинать каждый RUN, в котором вы хотите, чтобы переменная была сброшена, с unset VAR_NAME, что приведет к ее сбросу для только для RUN.

Если вы хотите, чтобы переменная не присутствовала в слоях, созданных Docker.

Предположим, что переменная содержит секрет, и слой может попасть в руки людей, у которых не должно быть секрета. В этом случае вы НЕ МОЖЕТЕ использовать ENV для установки переменной. Переменная, установленная с ENV, запекается в слоях, к которым она применяется, и не может быть удалена из этих слоев. В частности (при условии, что переменная имеет имя SENSITIVE), работает

RUN unset SENSITIVE

не делает ничего , чтобы удалить его из слоя. Приведенная выше команда unset удаляет только SENSITIVE из процесса оболочки, который запускается RUN. Это влияет только на эту оболочку. Это не повлияет на оболочки, порожденные CMD, ENTRYPOINT или любой командой, предоставленной при запуске docker run в командной строке.

Чтобы слои не содержали секрет, я бы использовал docker build --secret= и RUN --mount=type=secret.... Например, предполагая, что я сохранил свой секрет в файле с именем sensitive, у меня может быть RUN, например:

RUN --mount=type=secret,id=sensitive,target=/root/sensitive \
 export SENSITIVE=$(cat /root/sensitive) \
 && [[... do stuff that requires SENSITIVE ]] \

Обратите внимание, что команде, данной RUN, не обязательно заканчиваться на unset SENSITIVE. Из-за способа управления процессами и их средами, установка SENSITIVE в оболочке, порожденной RUN не имеет никакого эффекта помимо того, что порождает эта оболочка. Изменения среды в этой оболочке не будут влиять на будущие оболочки и не будут влиять на то, что Docker запекает в создаваемые им слои.

Затем сборку можно запустить с помощью:

$ DOCKER_BUILDKIT=1 docker build --secret id=secret,src=path/to/sensitive [...]

Среде для команды docker build требуется DOCKER_BUILDKIT=1 для использования BuildKit, поскольку этот метод передачи секретов доступен только в том случае, если Docker использует BuildKit для построения образов.

1 голос
/ 22 апреля 2019

В соответствии с докерской документацией вам нужно использовать команду оболочки:

FROM alpine
RUN export ADMIN_USER="mark" \
&& echo $ADMIN_USER > ./mark \
&& unset ADMIN_USER
CMD sh

Подробнее см. https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#env.

1 голос
/ 02 июля 2019

Если во время сборки образа нужны переменные, но они не должны сохраняться, просто очистите их.В следующем примере запущенный контейнер показывает пустые переменные env.

Dockerfile

# set proxy
ARG http_proxy
ARG https_proxy
ARG no_proxy
ENV http_proxy=$http_proxy
ENV https_proxy=$http_proxy
ENV no_proxy=$no_proxy

# ... do stuff that needs the proxy during the build, like apt-get, curl, et al.

# unset proxy
ENV http_proxy=
ENV https_proxy=
ENV no_proxy=

build.sh

docker build -t the-image \
    --build-arg http_proxy="$http_proxy" \
    --build-arg https_proxy="$http_proxy" \
    --build-arg no_proxy="$no_proxy" \
    --no-cache \
    .

run.sh

docker run --rm -i \
    the-image \
    sh << COMMANDS
        env
COMMANDS

Выход

no_proxy=
https_proxy=
http_proxy=
...
0 голосов
/ 22 апреля 2019

AFAIK, в Dockerfile нет операторов, которые изначально поддерживают эту функцию.Однако вы можете удалить его, используя обычную команду оболочки -

...   
ENV http_proxy=http://...
RUN unset http_proxy
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...