
Cuando aprendía a conducir, en mi primera clase el instructor salió marcha atrás en una intersección y luego dijo que nunca se debe hacer eso. Esta regla la recordé de inmediato y para toda la vida.
Lees a los niños 'Consejos dañinos' de Grigori Oster y ves lo fácil y natural que les resulta entender que no se debe hacer así.
Se han escrito muchos artículos sobre cómo escribir un Dockerfile correctamente. Pero no he encontrado instrucciones sobre cómo escribir Dockerfiles incorrectos. Estoy llenando ese vacío. Y quizás, en los proyectos que recibo para soporte, haya menos de esos Dockerfiles.
Todos los personajes, situaciones y Dockerfiles son ficticios. Si te reconoces, lo siento.
Creamos un Dockerfile, siniestro y horrible.
Petr (Desarrollador senior de Java/Ruby/PHP): Colega Vasili, ¿ya has subido el nuevo módulo en Docker?
Vasili (junior): No, no he podido, no logro entender este Docker. Hay tantos artículos que me deslumbran.
Petr: Nuestra fecha límite fue hace un año. Déjame ayudarte, mientras lo hacemos, nos aclaramos. Cuéntame, ¿qué es lo que no se te da?
Vasili: No puedo elegir la imagen base, para que sea mínima, pero que contenga todo lo necesario.
Petr: Toma la imagen de ubuntu, tiene todo lo necesario. Y si hay cosas innecesarias, ya servirán más adelante. Y no olvides poner la etiqueta latest para que la versión siempre sea la más reciente.
Y en el Dockerfile aparece la primera línea:
FROM ubuntu:latestPetr: ¿Qué hay después, en qué estuvimos escribiendo nuestro módulo?
Vasili: Pues en ruby, ahí deberían iniciarse un servidor web y un par de demonios de servicio.
Petr: Ah, lo que necesitamos: ruby, bundler, nodejs, imagemagick, y lo que sea... Y de paso, haz un upgrade para obtener los paquetes nuevos.
Vasili: ¿No vamos a crear un usuario para no hacerlo bajo root?
Petr: Bah, qué va, luego tendré que preocuparme por los permisos.
Vasili: Necesito tiempo, unos 15 minutos, para juntar todo esto en un solo comando, leí que...
(Petr interrumpe de manera brusca al inquisitivo y demasiado inteligente junior.)
Petr: Escribe comandos separados, así será más fácil de leer.
El Dockerfile crece:
FROM ubuntu:latest
RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full
RUN gem install bundler
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
RUN bundle install --without development test --path vendor/bundle
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*Entra Igor Ivanovich, DevOps (pero más Ops que Dev), gritando:
II: Petya, tus desarrolladores han vuelto a romper la base de datos de producción, ¿cuándo se va a acabar esto...?
Después de una pequeña discusión, Igor Ivanovich se calma y comienza a averiguar qué están haciendo sus colegas.
IA: ¿En qué están ocupados?
Vasiliy: Petr me está ayudando a crear un Dockerfile para el nuevo módulo.
IA: Déjame ver... ¿Qué han escrito aquí? Ustedes limpian el repositorio con un comando aparte, esto es una capa adicional... ¿Y cómo ponen las dependencias si no han copiado el Gemfile? Y en general, esto no sirve.
Petr: Por favor, ocúpate de tus propios asuntos, nosotros resolveremos esto.
Igor Ivanovich suspira con nostalgia y se va a investigar quién rompió la base de datos.
Petr: Sí, pero lo que dijo sobre el código es correcto, hay que meterlo en la imagen. Y pongamos ssh y supervisor de inmediato, porque ¿cómo vamos a iniciar los demonios?
Vasiliy: Entonces primero copiaré el Gemfile y el Gemfile.lock, después instalaré todo, y luego copiaré todo el proyecto. Si el Gemfile no cambia, la capa se tomará del caché.
Petr: ¿Por qué todos están con estas capas? Copia todo de una vez. Copia todo. En la primera línea.
El Dockerfile ahora se ve así:
FROM ubuntu:latest
COPY .\/ \/app
WORKDIR \/app
RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
RUN gem install bundler
RUN curl -sL https:\/\/deb.nodesource.com\/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
RUN bundle install --without development test --path vendor\/bundle
RUN rm -rf \/usr\/local\/bundle\/cache\/*.gem
RUN apt-get clean
RUN rm -rf \/var\/lib\/apt\/lists\/* \/tmp\/* \/var\/tmp\/* Petr: Entonces, ¿qué sigue? ¿Tienes los archivos de configuración para supervisor?
Vasiliy: No, no los tengo. Pero los haré rápidamente.
Petr: Hazlo después. Ahora hagamos un script de inicialización que inicie todo. Bien, primero inicias ssh con nohup para que podamos conectarnos al contenedor y ver qué salió mal. Luego inicias supervisor de la misma manera. Y después simplemente iniciarás passenger.
V: Pero leí que debe haber un solo proceso, así Docker sabrá que algo salió mal y podrá reiniciar el contenedor.
P: No te preocupes por tonterías. Y además, ¿cómo? ¿Cómo vas a iniciar todo eso en un solo proceso? Que Igor Ivanovich se preocupe por la estabilidad, no por nada recibe su salario. Nuestro trabajo es escribir código. Y en general, que agradezca que hemos escrito el Dockerfile por él.
Después de 10 minutos y dos videos de gatos.
V: Ya hice todo. También añadí más comentarios.
P: ¡Muéstrame!
Versión fresca del Dockerfile:
DE FROM ubuntu:latest
# Copiamos el código fuente
COPY . /app
WORKDIR /app
# Actualizamos la lista de paquetes
RUN apt-get update
# Actualizamos los paquetes
RUN apt-get upgrade
# Instalamos los paquetes necesarios
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
# Instalamos bundler
RUN gem install bundler
# Instalamos nodejs que se utiliza para construir la estática
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
# Instalamos las dependencias
RUN bundle install --without development test --path vendor/bundle
# Limpiamos los cachés
RUN rm -rf /usr/local/bundle/cache/*.gem
RUN apt-get clean
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Ejecutamos el script al inicio del contenedor, que iniciará todo lo demás.
CMD ["/app/init.sh"]P: Excelente, me gusta. Y los comentarios en ruso son convenientes y legibles, todos deberían trabajar así. Te he enseñado todo, ahora podrás hacerlo tú solo. Vamos a tomar un café...
Bueno, aquí tenemos un Dockerfile perfectamente horrible, al ver el cual Igor Ivanovich querrá renunciar y le dolerán los ojos durante una semana. El Dockerfile, por supuesto, podría ser aún peor, no hay límites para la perfección. Pero por ahora, esto funcionará.
Quisiera terminar con una cita de Grigori Oster:
Si aún no has decidido firmemente
El camino en la vida,
Y no sabes por dónde empezar
Tu camino laboral,
Rompe las bombillas en los pasillos —
La gente te dirá "Gracias".
Ayudarás a la gente
A ahorrar electricidad.
Fuente: habr.com
