Docker:糟糕的建议

Docker:糟糕的建议

当我学开车的时候,第一节课教练把车倒车开进路口,然后说你不应该这样做——绝对不可以。 我立即记住了这条规则,并终生记住。

当你给孩子们读格里戈里·奥斯特的《坏建议》时,你会发现他们很容易、很自然地意识到他们不应该这样做。

关于如何正确编写 Dockerfile 已经写了很多文章。 但我没有遇到有关如何编写不正确的 Dockerfile 的说明。 我正在填补这个空白。 也许在我获得支持的项目中,这样的 dockerfile 会更少。

所有人物、场景和 Dockerfile 均属虚构。 如果你认识自己的话,对不起。

创建一个 Dockerfile,不祥且可怕

Peter(高级java/rubby/php开发人员):Vasily同事,您已经将新模块上传到Docker了吗?
Vasily(初级):不,我没有时间,我无法用这个 Docker 搞清楚。 这方面的文章太多了,让人眼花缭乱。

彼得:我们一年前就有了最后期限。 让我来帮助你,我们会在这个过程中解决这个问题。 告诉我什么对你不起作用。

Vasily:我无法选择基本图像,因此它很小,但具有您需要的一切。
Peter:以 ubuntu 镜像为例,它有你需要的一切。 而且很多不必要的东西,以后都会派上用场的。 并且不要忘记添加最新标签,以便版本始终是最新的。

第一行出现在 Dockerfile 中:

FROM ubuntu:latest

Peter:下一步是什么,我们用什么来编写我们的模块?
Vasily:Ruby,有一个 Web 服务器和几个服务守护进程应该启动。
Peter:是的,我们需要什么:ruby、bundler、nodejs、imagemagick 以及其他什么...同时,进行升级以获得新的软件包。
Vasily:我们不会创建一个用户,这样我们就不会处于 root 状态了?
彼得:操,那你还得玩弄权利。
Vasily:我需要时间,大约 15 分钟,将所有内容整合到一个命令中,我读到……
(彼得粗鲁地打断了这位细心且非常聪明的后辈。)
Peter:用单独的命令写,这样会更容易阅读。

Dockerfile 增长:

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/*

然后 Igor Ivanovich,DevOps(但更多是运维而不是 Dev),冲进办公室大喊:

AI:Petya,你们的开发者又破坏了食物数据库,这什么时候结束……

一场小冲突后,伊戈尔·伊万诺维奇冷静下来,开始了解他的同事在这里做什么。

艾:你在做什么?
Vasily:Peter 正在帮助我为新模块创建 Dockerfile。
AI:让我看看...你在这里写了什么,你用一个单独的命令清理存储库,这是一个附加层...但是如果你没有复制 Gemfile,你如何安装依赖项! 一般来说,这不好。
彼得:请忙你的事吧,我们会想办法解决的。

伊戈尔·伊万诺维奇悲伤地叹了口气,然后离开去查明是谁破坏了数据库。

彼得:是的,但他对代码的看法是对的,我们需要将其推入图像中。 让我们立即安装 ssh 和supervisor,否则我们将启动守护进程。

Vasily:然后我将首先复制 Gemfile 和 Gemfile.lock,然后安装所有内容,然后复制整个项目。 如果 Gemfile 没有改变,则将从缓存中获取该图层。
Peter:为什么你们都用这些图层,一次性复制所有内容。 立即复制。 第一行。

Dockerfile 现在看起来像这样:

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/* 

彼得:那么,接下来怎么办? 你有主管的配置吗?
瓦西里:不,不。 但我会很快做的。
彼得:那你就去做吧。 现在让我们草拟一个将启动所有内容的初始化脚本。 好的,那么你用 nohup 启动 ssh,这样我们就可以连接到容器并查看出了什么问题。 然后以同样的方式运行supervisor。 好吧,那你就跑乘客吧。
问:但我读到应该有一个进程,这样 Docker 就会知道出了问题并可以重新启动容器。
P:别用废话来打扰你的头脑。 一般来说,怎么样? 如何在一个进程中运行所有这些? 让伊戈尔·伊万诺维奇考虑稳定,他收到薪水不是白费的。 我们的工作就是写代码。 总的来说,让他对我们为他编写的文档文件表示感谢。

10 分钟和两个关于猫的视频。

问:我已经做了一切。 我添加了更多评论。
普:告诉我!

Dockerfile 的最新版本:

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

# Устанавливаем bundler
RUN gem install bundler

# Устанавливаем nodejs используется для сборки статики
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/* 

# Запускаем скрипт, при старте контейнера, который запустит все остальное.
CMD [“/app/init.sh”]

普:太好了,我喜欢。 而且评论都是俄语的,方便易读,大家都会这样操作。 我已经教你一切了,剩下的你可以自己做。 我们去喝杯咖啡吧...

好吧,现在我们有了一个非常糟糕的 Dockerfile,看到它会让 Igor Ivanovich 想退出,他的眼睛又会疼一个星期。 当然,Dockerfile 可能更糟,完美无极限。 但首先,这样就可以了。

我想引用格里戈里·奥斯特的一句话作为结束:

如果您还不确定
我们选择了人生的道路,
而你不知道为什么
开启你的劳动之旅,
打破走廊里的灯泡 -
人们会对你说“谢谢”。
你会帮助人民
节约用电。

来源: habr.com

添加评论