我如何在Docker内部启动Docker及其结果

大家好! 在上一篇文章中 ,我答应谈论Docker在Docker中的启动以及应用本课程的实际方面。 现在是兑现我们的诺言的时候了。 一位经验丰富的开发人员可能会辩称,那些需要在Docker内部使用Docker的人只需将Docker恶魔套接字从容器内的主机扔掉,这在99%的情况下就足够了。 但是请不要着急向我扔饼干,因为我们将谈论Docker内部真正启动Docker的问题。 该解决方案具有许多可能的应用领域,本文仅涉及其中之一,因此请坐下来并伸直双臂。


图片

开始


一切始于9月的一个下雨天,当时我以5美元的价格清洁了Digital Ocean的租车,因为Docker用其映像和容器填充了所有24 GB的可用磁盘空间,所以这辆车紧紧地挂了起来。 具有讽刺意味的是,所有这些映像和容器都是瞬态的,仅在每次发布新版本的库或框架时才需要测试我的应用程序的性能。 我试图编写shell脚本并配置垃圾清理的王冠时间表,但这并没有节省:每次不可避免地,我的服务器磁盘空间被吃光了,服务器挂起了(最好)。 在某个时候,我遇到了一篇有关如何在容器中运行Jenkins以及如何通过抛出的docker daemon套接字创建和删除程序集管道的文章。 我喜欢这个主意,但我决定继续尝试在Docker内部直接启动Docker进行试验。 在我看来,这是一个完全合乎逻辑的决定,即抽出docker映像并创建在另一个容器内测试所需的所有应用程序的容器(我们称其为暂存容器)。 想法是运行带有-rm标志的暂存容器,该容器在停止时会自动删除整个容器及其所有内容。 我在Docker本身( https://hub.docker.com/_/docker )上浏览了Docker映像,但结果实在太笨拙了,我无法按需使用它,我想自己走一路。


练习 颠簸


我着手根据需要使容器工作,并继续进行实验,结果产生了无数的圆锥体。 我遭受自我折磨的结果是以下算法:


  1. 我们以交互模式启动Docker容器。


    docker run --privileged -it docker:18.09.6 

    注意容器的版本,向右或向左移动,您的DinD会变成南瓜。 实际上,随着新版本的发布,一切都经常崩溃。
    我们必须立即进入外壳。


  2. 尝试找出正在运行的容器(答案:无),但无论如何都要执行命令:


     docker ps 

    您会有些惊讶,但是事实证明Docker守护程序甚至没有运行:


     error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 192.168.65.1:53: no such host 

  3. 让我们自己运行它:


     dockerd & 

    另一个不愉快的惊喜:


     failed to start daemon: Error initializing network controller: error obtaining controller instance: failed to create NAT chain DOCKER: Iptables not found 

  4. 安装iptables和bash软件包(在bash中工作比在sh中工作更愉快):


     apk add --no-cache iptables bash 

  5. 我们开始狂欢。 终于,我们回到了通常的外壳中


  6. 尝试再次启动docker:


     dockerd & 

    我们应该看到一个长长的日志表结尾:


     INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock 

  7. 按Enter键。 我们又回来了。



从现在开始,我们可以尝试在Docker容器内启动其他容器,但是如果我们想在Docker容器内提升另一个Docker容器,或者出现问题并且该容器将“飞出”怎么办? 重新开始。


自己的DinD容器和新实验



为了不一次又一次地重复上述步骤,我创建了自己的DinD容器:


https://github.com/alekslitvinenk/dind


可用的DinD解决方案使我有机会递归地在Docker中运行Docker并进行更大胆的实验。
我现在将描述一个这样的(成功的)运行MySQL和Nodejs的实验。
最不耐烦的人可以看到这里的情况



因此,让我们开始:


  1. 交互式启动DinD。 在此版本的DinD中,我们需要手动映射子容器可以使用的所有端口(我已经在做此工作)


     docker run --privileged -it \ -p 80:8080 \ -p 3306:3306 \ alekslitvinenk/dind 

    我们发现自己不知所措,从那里我们可以立即开始发射辅助容器。


  2. 我们启动MySQL:


     docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql 

  3. 我们以与本地连接数据库相同的方式连接数据库。 确保一切正常。


  4. 我们启动第二个容器:


     docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server 

    请注意,这里的端口映射将完全是8080:8080 ,因为我们已经将端口80从主机映射到端口8080上的父容器。


  5. 我们在浏览器中转到localhost,我们确信服务器会回答“ Hello World!”。



以我为例,封闭的docker容器的实验是非常积极的,我将继续开发该项目并将其用于登台。 在我看来,这是比相同的Kubernetes和Jenkins X更轻巧的解决方案。但这是我的主观意见。


我认为这就是今天的文章。 在下一篇文章中,我将更详细地描述在Docker中递归启动Docker并将目录安装到嵌套容器深处的实验。


PS:如果您觉得这个项目有用,那么请在GitHub上给它加一个星号,并分叉并告诉您的朋友。


Edit1已修复的错误,主要针对2个视频

Source: https://habr.com/ru/post/zh-CN477464/


All Articles