¿Cómo escribir comandos con varias líneas en Dockerfile conservando las nuevas líneas?


84

Quiero escribir el siguiente comando RUN en el Dockerfile. Pero Docker no conserva las nuevas líneas.

RUN echo "[repo] \
name            = YUM Repository \
baseurl         = https://example.com/packages/ \
enabled         = 1 \
gpgcheck        = 0" > /etc/yum.repos.d/Repo.repoxyz

Sé que \al final de cada línea se escapa la nueva línea. Pero, ¿hay alguna forma de que pueda escribir varias líneas conservando la nueva línea?


¿Está utilizando una plataforma que no sea * nix? Porque esto funciona bien para mí en Linux.
usuario

@usuario, estaba usando Linux.
Venkata Jaswanth

Respuestas:


114

Puede utilizar lo que se denomina "cotización ANSI-C" con $'...'. Originalmente era una característica de ksh93 pero ahora está disponible en bash, zsh, mksh, FreeBSD sh y en el ash de busybox (pero solo cuando está compilado con ENABLE_ASH_BASH_COMPAT).

Como RUN usa /bin/shcomo shell por defecto , se requiere que cambie primero a algo como bash usando la instrucción SHELL.

Comience su comando con $', termínelo con 'y utilícelo \n\para nuevas líneas, así:

SHELL ["/bin/bash", "-c"]

RUN echo $'[repo] \n\
name            = YUM Repository \n\
baseurl         = https://example.com/packages/ \n\
enabled         = 1 \n\
gpgcheck        = 0' > /etc/yum.repos.d/Repo.repoxyz

4
Es sintaxis bash. Consulte esta pregunta para obtener más información: stackoverflow.com/a/11966402/1395437
Daniel Zolnai

13
Por favor, explique lo que está haciendo, no deje caer una solución opaca
Édouard Lopez

25
Una advertencia: la $' ... \n\ técnica depende del shell que RUNutilice Docker bash. En algunos sistemas (como Ubuntu), el shell RUN que utiliza /bin/shes a menudo un enlace al dashque NO lo es bashy no comprende la $'sintaxis.
Anon

2
como dijo @Anon, esto NO FUNCIONARÁ si se ejecuta en otro lugar que no sea bash. (no funciona en Oh My Zshninguno de los dos)
Rafa

1
@Anon bien, funciona en Alpine Linux (actualmente estoy en 3.10.2) que usa shell.
suchoss

52

Yo usé printf. Escribir todo el texto en una línea usando "\ n".

Ejecutando:

RUN printf 'example \ntext \nhere' >> example.txt

inserciones:

example
text
here

en ejemplo.txt


19

Puedes usar:

RUN echo -e "\
[repo] \n\
name            = YUM Repository \n\
baseurl         = https://example.com/packages/ \n\
enabled         = 1 \n\
gpgcheck        = 0\
" > /etc/yum.repos.d/Repo.repoxyz

De esta manera, tendrá una forma rápida de verificar el contenido del archivo. Solo debe tener en cuenta que debe terminar cada línea con \e insertar el \ncuando sea necesario.


1
Esto requiere echo -einterpretar\n
Patrick Bergner

5

Terminé usando una combinación de los ejemplos enumerados anteriormente ya que la nueva línea \nno funcionó con echo.

RUN printf 'example \n\
text \n\
here' >> example.txt

Produce lo siguiente, como se esperaba:

example
text
here

¿En qué se diferencia su respuesta de la de CTodea?
El padrino

@TheGodfather Ese es un ejemplo de varias líneas. Mejor responde también a la pregunta original.
Sergey

2

Puede que te ayude ( https://github.com/jen-soft/pydocker )

[Dockerfile.py]

from pydocker import DockerFile  # sudo pip install -U pydocker

d = DockerFile(base_img='debian:8.2', name='jen-soft/custom-debian:8.2')

d.RUN_bash_script('/opt/set_repo.sh', r'''
cat >/etc/apt/sources.list <<EOL
deb     http://security.debian.org/ jessie/updates main
deb-src http://security.debian.org/ jessie/updates main
EOL
apt-get clean && apt-get update
''')

d.EXPOSE = 80
d.WORKDIR = '/opt'
d.CMD = ["python", "--version"]

# d.generate_files()
d.build_img()

# sudo wget -qO- https://get.docker.com/ | sh

python Dockerfile.py
docker images

-1

Puede ejecutar RUN varias veces para completar su archivo:

RUN echo "[repo]" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "name            = YUM Repository" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "baseurl         = https://example.com/packages/" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "enabled         = 1" >> /etc/yum.repos.d/Repo.repoxyz
RUN echo "gpgcheck        = 0" >> /etc/yum.repos.d/Repo.repoxyz

Esta puede no ser la solución óptima porque crea una nueva capa para cada comando RUN. Aún así, cada capa será tan grande como el cambio que realice, que en este caso es del orden de Bytes (la primera capa RUN debe ser de 7 bytes).

El beneficio de esta solución es que funcionará con todos los shells.


1
Probablemente sea mejor combinar estos comandos con &&mejores propósitos de almacenamiento en caché, registro reducido y Dockerfiletiempos de compilación más rápidos
JohannesB
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.