Docker 快速入门
1 Docker 是什么?
Docker 是一个开源的容器引擎,而一个容器其实是一个虚拟化的独立的环境,因此开发者可以将应用打包到这样的一个 docker 容器中,然后发布到任何可以运行 docker 容器的机器中,实现一次打包多处部署,解决了因为环境问题而导致的部署难题。
1.1 容器是什么?
与 容器 对应的一个概念就是 镜像,镜像可以看做我们平时装系统的镜像,里面就是一个运行环境。当然我比较喜欢将镜像比作一个我们面向对象编程中的 类,而一个容器就是一个类的 实例,因此可以根据一个镜像,创建出很多个容器。每一个容器都是具体的,我们可以在容器上面做出更改,然后再把这个容器打包成一个新的镜像,从而以后可以根据改动后的镜像创建出新的容器。而容器本身可以简单理解为是一个虚拟独立的运行环境,我们要做的是中这个环境中打包我们的应用,以便于再次部署。
2 安装 Docker
Gentoo
<span class="com">#</span><span class="pln"> emerge </span><span class="pun">--</span><span class="pln">ask docker</span>
CentOS
<span class="com">#</span><span class="kwd">yum</span><span class="pln"> install docker</span><span class="pun">-</span><span class="pln">ce</span>
Ubuntu
<span class="com">#</span><span class="kwd">apt-get</span><span class="pln"> install docker</span><span class="pun">-</span><span class="pln">ce</span>
Arch
<span class="com">#</span><span class="pln"> pacman </span><span class="pun">-</span><span class="pln">S docker</span>
2.1 启动 docker 守护进程
<span class="com">#</span><span class="kwd">systemctl</span><span class="pln"> start docker</span>
3 docker 命令介绍
<span class="com">#</span><span class="pln"> docker </span><span class="pun">--</span><span class="pln">help</span>
<span class="pun">管理命令:</span>
<span class="pln">container </span><span class="pun">管理容器</span>
<span class="pln">image </span><span class="pun">管理镜像</span>
<span class="pln">network </span><span class="pun">管理网络</span>
<span class="pun">命令:</span>
<span class="pln">attach </span><span class="pun">介入到一个正在运行的容器</span>
<span class="pln">build </span><span class="pun">根据</span><span class="typ">Dockerfile</span><span class="pun">构建一个镜像</span>
<span class="pln">commit </span><span class="pun">根据容器的更改创建一个新的镜像</span>
<span class="kwd">cp</span><span class="pun">在本地文件系统与容器中复制</span><span class="pun">文件/文件夹</span>
<span class="pln">create </span><span class="pun">创建一个新容器</span>
<span class="kwd">exec</span><span class="pun">在容器中执行一条命令</span>
<span class="pln">images </span><span class="pun">列出镜像</span>
<span class="kwd">kill</span><span class="pun">杀死一个或多个正在运行的容器</span>
<span class="pln">logs </span><span class="pun">取得容器的日志</span>
<span class="pln">pause </span><span class="pun">暂停一个或多个容器的所有进程</span>
<span class="kwd">ps</span><span class="pun">列出所有容器</span>
<span class="pln">pull </span><span class="pun">拉取一个镜像或仓库到</span><span class="pln"> registry</span>
<span class="pln">push </span><span class="pun">推送一个镜像或仓库到</span><span class="pln"> registry</span>
<span class="kwd">rename</span><span class="pun">重命名一个容器</span>
<span class="pln">restart </span><span class="pun">重新启动一个或多个容器</span>
<span class="kwd">rm</span><span class="pun">删除一个或多个容器</span>
<span class="pln">rmi </span><span class="pun">删除一个或多个镜像</span>
<span class="pln">run </span><span class="pun">在一个新的容器中执行一条命令</span>
<span class="pln">search </span><span class="pun">在</span><span class="typ">Docker</span><span class="typ">Hub</span><span class="pun">中搜索镜像</span>
<span class="pln">start </span><span class="pun">启动一个或多个已经停止运行的容器</span>
<span class="pln">stats </span><span class="pun">显示一个容器的实时资源占用</span>
<span class="pln">stop </span><span class="pun">停止一个或多个正在运行的容器</span>
<span class="pln">tag </span><span class="pun">为镜像创建一个新的标签</span>
<span class="kwd">top</span><span class="pun">显示一个容器内的所有进程</span>
<span class="pln">unpause </span><span class="pun">恢复一个或多个容器内所有被暂停的进程</span>
在子命令中还有更多丰富的选项,可以使用 docker COMMAND --help
查看。例如:
<span class="com">#</span><span class="pln"> docker run </span><span class="pun">--</span><span class="pln">help</span>
4 docker 使用实战
接下来,我将利用 docker 部署一个 Nginx 服务器,作为讲解的例子。 要创建一个容器,那么我们必须先要有一个用于创建容器的镜像。 在 docker hub 中查找 nginx 相关镜像。
<span class="com">#</span><span class="pln"> docker search nginx</span>
<span class="pln">NAME DESCRIPTION STARS OFFICIAL AUTOMATED</span>
<span class="pln">nginx </span><span class="typ">Official</span><span class="pln"> build of </span><span class="typ">Nginx</span><span class="pun">.</span><span class="lit">6959</span><span class="pun">[</span><span class="pln">OK</span><span class="pun">]</span>
<span class="pln">jwilder</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">-</span><span class="pln">proxy </span><span class="typ">Automated</span><span class="typ">Nginx</span><span class="pln"> reverse proxy </span><span class="kwd">for</span><span class="pln"> docker c</span><span class="pun">...</span><span class="lit">1134</span><span class="pun">[</span><span class="pln">OK</span><span class="pun">]</span>
<span class="pln">richarvey</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">-</span><span class="pln">php</span><span class="pun">-</span><span class="pln">fpm </span><span class="typ">Container</span><span class="pln"> running </span><span class="typ">Nginx</span><span class="pun">+</span><span class="pln"> PHP</span><span class="pun">-</span><span class="pln">FPM capable </span><span class="pun">...</span><span class="lit">452</span><span class="pun">[</span><span class="pln">OK</span><span class="pun">]</span>
<span class="pun">...</span>
<span class="pun">...</span>
拉取官方镜像,其中上面的非官方镜像是用户们根据自己的需要制作的镜像,方便大家的使用。
<span class="com">#</span><span class="pln"> docker pull nginx</span>
<span class="typ">Using</span><span class="kwd">default</span><span class="pln"> tag</span><span class="pun">:</span><span class="pln"> latest</span>
<span class="pln">latest</span><span class="pun">:</span><span class="typ">Pulling</span><span class="kwd">from</span><span class="pln"> library</span><span class="pun">/</span><span class="pln">nginx</span>
<span class="pln">afeb2bfd31c0</span><span class="pun">:</span><span class="typ">Pull</span><span class="pln"> complete</span>
<span class="lit">7ff5d10493db</span><span class="pun">:</span><span class="typ">Downloading</span><span class="pun">[===============></span><span class="pun">]</span><span class="lit">6.651</span><span class="pln"> MB</span><span class="pun">/</span><span class="lit">21.87</span><span class="pln"> MB</span>
<span class="pln">d2562f1ae1d0</span><span class="pun">:</span><span class="typ">Download</span><span class="pln"> complete</span>
在这里顺便说一下,docker 镜像是分层存储的,所以上面的 nginx 镜像有 3 层,另外每根据新的容器制作一个新的镜像以后会给这个镜像加上一层。
接下来直接利用这个镜像启动一个新的容器:
<span class="com">#</span><span class="pln"> docker run </span><span class="pun">--</span><span class="pln">name </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx </span><span class="pun">-</span><span class="pln">d </span><span class="pun">-</span><span class="pln">p </span><span class="lit">8080</span><span class="pun">:</span><span class="lit">80</span><span class="pln"> nginx</span>
此时中浏览器中输入:http://localhost:8080/ 即可访问 nginx。 参数解释:
--name
为容器取一个名字-p
参数语法为-p host port:container port
;-p 8080:80
将主机上的8080端口绑定到容器上的80端口,因此在主机中访问8080端口时其实就是访问 nginx 容器的80端口-d
后台运行容器
然后我们来看一个更复杂的例子:
<span class="com">#</span><span class="pln"> docker run </span><span class="pun">--</span><span class="pln">name </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx \ </span>
<span class="pun">-</span><span class="pln">v </span><span class="pun">/</span><span class="pln">host</span><span class="pun">/</span><span class="pln">path</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">conf</span><span class="pun">:</span><span class="str">/etc/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">conf</span><span class="pun">:</span><span class="pln">ro \</span>
<span class="pun">-</span><span class="pln">v </span><span class="pun">/</span><span class="pln">some</span><span class="pun">/</span><span class="pln">html</span><span class="pun">:</span><span class="str">/usr/</span><span class="pln">share</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">html</span><span class="pun">:</span><span class="pln">ro \</span>
<span class="pun">-</span><span class="pln">p </span><span class="lit">8080</span><span class="pun">:</span><span class="lit">80</span><span class="pln"> \</span>
<span class="pun">-</span><span class="pln">d nginx</span>
这个例子多了一个参数 -v
,这个参数的作用是把本地的文件或者文件夹挂载到容器中,其中最后面的 ro
或者 rw
控制这个挂载是否可写。
-v
参数语法为-v host dir:container dir[:ro|rw]
上面的命令将本地文件中的 nginx.conf
配置文件挂载到容器,并且将要展示的静态页面也挂载到容器。 注意:在容器执行一条命令以后,当这个命令结束运行,容器也会结束运行。
接下来让我们看看 docker 别的命令。
查看所有运行中的容器:
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">ps</span>
<span class="pln">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span>
<span class="lit">1fe91b5a4cd4</span><span class="pln"> nginx </span><span class="str">"nginx -g 'daemon ..."</span><span class="lit">39</span><span class="pln"> minutes ago </span><span class="typ">Up</span><span class="lit">39</span><span class="pln"> minutes </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:</span><span class="lit">8080</span><span class="pun">-></span><span class="lit">80</span><span class="pun">/</span><span class="pln">tcp </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">ps</span><span class="pun">-</span><span class="pln">a </span><span class="com">### 列出包括未运行的容器</span>
查看容器运行日志:
<span class="com">#</span><span class="pln"> docker logs </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
<span class="lit">172.17</span><span class="pun">.</span><span class="lit">0.1</span><span class="pun">-</span><span class="pun">-</span><span class="pun">[</span><span class="lit">05</span><span class="pun">/</span><span class="typ">Oct</span><span class="pun">/</span><span class="lit">2017</span><span class="pun">:</span><span class="lit">07</span><span class="pun">:</span><span class="lit">31</span><span class="pun">:</span><span class="lit">11</span><span class="pun">+</span><span class="lit">0000</span><span class="pun">]</span><span class="str">"GET / HTTP/1.1"</span><span class="lit">200</span><span class="lit">612</span><span class="str">"-"</span><span class="str">"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"</span><span class="str">"-"</span>
<span class="lit">2017</span><span class="pun">/</span><span class="lit">10</span><span class="pun">/</span><span class="lit">05</span><span class="lit">07</span><span class="pun">:</span><span class="lit">31</span><span class="pun">:</span><span class="lit">11</span><span class="pun">[</span><span class="pln">error</span><span class="pun">]</span><span class="lit">7</span><span class="com">#</span><span class="lit">7</span><span class="pun">:</span><span class="pun">*</span><span class="lit">1</span><span class="pln"> open</span><span class="pun">()</span><span class="str">"/usr/share/nginx/html/favicon.ico"</span><span class="pln"> failed </span><span class="pun">(</span><span class="lit">2</span><span class="pun">:</span><span class="typ">No</span><span class="pln"> such </span><span class="kwd">file</span><span class="kwd">or</span><span class="pln"> directory</span><span class="pun">),</span><span class="pln"> client</span><span class="pun">:</span><span class="lit">172.17</span><span class="pun">.</span><span class="lit">0.1</span><span class="pun">,</span><span class="pln"> server</span><span class="pun">:</span><span class="pln"> localhost</span><span class="pun">,</span><span class="pln"> request</span><span class="pun">:</span><span class="str">"GET /favicon.ico HTTP/1.1"</span><span class="pun">,</span><span class="pln"> host</span><span class="pun">:</span><span class="str">"localhost:8080"</span>
重启容器:
<span class="com">#</span><span class="pln"> docker restart </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
<span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
停止运行一个容器:
<span class="com">#</span><span class="pln"> docker stop </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
<span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">ps</span>
<span class="pln">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span>
启动一个已经存在的容器:
<span class="com">#</span><span class="pln"> docker start </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
<span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">ps</span>
<span class="pln">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span>
<span class="lit">1fe91b5a4cd4</span><span class="pln"> nginx </span><span class="str">"nginx -g 'daemon ..."</span><span class="lit">50</span><span class="pln"> minutes ago </span><span class="typ">Up</span><span class="lit">3</span><span class="pln"> seconds </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:</span><span class="lit">8080</span><span class="pun">-></span><span class="lit">80</span><span class="pun">/</span><span class="pln">tcp </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
直接杀死一个运行中的容器:
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">kill</span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
重命名容器:
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">rename</span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx </span><span class="kwd">new</span><span class="pun">-</span><span class="pln">nginx</span>
删除容器:
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">rm</span><span class="kwd">new</span><span class="pun">-</span><span class="pln">nginx</span>
查看本机所有镜像:
<span class="com">#</span><span class="pln"> docker imags</span>
使用已经存在的容器创建一个镜像:
<span class="com">#</span><span class="pln"> docker commit </span><span class="pun">-</span><span class="pln">m </span><span class="str">"nothing changed"</span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">-</span><span class="pln">image</span>
<span class="pln">sha256</span><span class="pun">:</span><span class="pln">f02483cdb842a0dc1730fe2c653603fa3271e71c31dbb442caccd7ad64860350</span>
<span class="com">#</span><span class="pln"> docker images</span>
<span class="pln">REPOSITORY TAG IMAGE ID CREATED SIZE</span>
<span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">-</span><span class="pln">image latest f02483cdb842 </span><span class="lit">6</span><span class="pln"> seconds ago </span><span class="lit">108</span><span class="pln"> MB</span>
<span class="pln">nginx latest da5939581ac8 </span><span class="lit">3</span><span class="pln"> weeks ago </span><span class="lit">108</span><span class="pln"> MB</span>
使用我们自己创建的镜像创建容器:
<span class="com">#</span><span class="pln"> docker run </span><span class="pun">--</span><span class="pln">name </span><span class="kwd">test</span><span class="pun">-</span><span class="pln">d </span><span class="pun">-</span><span class="pln">p </span><span class="lit">8081</span><span class="pun">:</span><span class="lit">80</span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">-</span><span class="pln">image</span>
<span class="lit">12ba86eabdef0121d875bdb547f1101d4eb54ff7cb36e20214fb1388659af83d</span>
<span class="com">#</span><span class="pln"> docker </span><span class="kwd">ps</span>
<span class="pln">CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES</span>
<span class="lit">12ba86eabdef</span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span><span class="pun">-</span><span class="pln">image </span><span class="str">"nginx -g 'daemon ..."</span><span class="lit">7</span><span class="pln"> seconds ago </span><span class="typ">Up</span><span class="lit">5</span><span class="pln"> seconds </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:</span><span class="lit">8081</span><span class="pun">-></span><span class="lit">80</span><span class="pun">/</span><span class="pln">tcp </span><span class="kwd">test</span>
<span class="lit">299f4ede9e79</span><span class="pln"> nginx </span><span class="str">"nginx -g 'daemon ..."</span><span class="lit">11</span><span class="pln"> minutes ago </span><span class="typ">Up</span><span class="lit">11</span><span class="pln"> minutes </span><span class="lit">0.0</span><span class="pun">.</span><span class="lit">0.0</span><span class="pun">:</span><span class="lit">8080</span><span class="pun">-></span><span class="lit">80</span><span class="pun">/</span><span class="pln">tcp </span><span class="kwd">my</span><span class="pun">-</span><span class="pln">nginx</span>
如果我们使用的容器的启动命令是一个 shell ,那么我们可以使用 attach
命令来介入这个容器,就跟我们使用 ssh
连接一台服务器差不多。
<span class="com">#</span><span class="pln"> docker attach some</span><span class="pun">-</span><span class="pln">container</span>
在创建一个容器时直接启动一个可交互式的 shell, 并且退出后自动删除容器:
<span class="com">#</span><span class="pln"> docker run </span><span class="pun">-</span><span class="pln">it </span><span class="pun">--</span><span class="kwd">rm</span><span class="pln"> centos</span>
总结
本文介绍了 docker 的简单用法,同时也给出了一个实际的例子用来展示 docker 命令的各种操作。作为一个快速入门的文章,本文写的相对有点简单,很多概念上的东西还需要求查看别的资料理解,但是看完本文应该就具备使用 docker 的基本能力了。此外,后续的文章应该会写一点 Dockerfile
与 docker-compose
相关的内容。
更多Docker相关教程见以下内容:
Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里