美文网首页
Docker 基础知识

Docker 基础知识

作者: Vinc | 来源:发表于2018-07-24 17:57 被阅读141次

本文是泊学网站对应章节的归纳总结,原文视频和文字内容更加详实深入。强烈推荐泊学的一手 Swift 视频学习资料!

  • 一、创建并运行你的第一个容器
    • 1、安装Docker
    • 2、我们究竟都安装了什么?
    • 3、启动自己的第一个容器
  • 二、容器里究竟有些什么东西
    • 1、两种访问inspect结果的方法
  • 三、清理和容器有关的资源
    • 1、如何删除容器
    • 2、如何删除镜像
  • 四、如何与容器交互
    • 1、恢复已经结束的容器
  • 五、通过容器启动一个Nginx server
    • 1、安装并启动Nginx
    • 2、通过host访问容器中的Web服务
  • 六、通过Volumn共享文件

一、创建并运行你的第一个容器

1、安装Docker

安装社区版(Docker CE)后,启动Docker,就会在系统状态栏上看到一个鲸鱼图标:

-w580

在这个菜单中,有4个内容是我们常用的:

  • Docker is running表示当前Docker的执行状态;
  • Preferences...是Docker设置,通常我更习惯通过命令行来处理;
  • Kitematic是一个GUI的容器镜像管理界面,同样,我更习惯用命令行操作,大家感兴趣可以自己去看看;
  • Repositories可以理解成是Docker版的Github,上面有各种来自官方的和第三方的容器镜像。是我们安装各种环境的主要来源;

2、我们究竟都安装了什么?

接下来,我们看一下通过Docker的安装包,我们究竟都安装了那些东西。打开Terminal,输入dockerTab,可以看到,实际上我们安装了4个工具:

6

其中:

  • docker:是docker的管理程序,我们创建和销毁容器、管理docker镜像都是通过这个命令完成的;
  • docker-compose:可以理解为是docker容器的自动化工具,我们可以通过一个脚本来自动化构建一个多容器环境的构建;
  • docker-machine:在本地环境,我们很少使用它。简单来说,它可以用让我们像使用本地容器一样的来管理远程容器;
  • docker-credential-osxkeychain:用来把docker使用的证书保存到OS X的keychain,暂时我们不会用到它;

3、启动自己的第一个容器

所谓Docker里的Hello World,当然就是创建并运行一个自己的容器。在现在这个阶段,我们把容器就理解成操作系统中的进程就好了,甚至docker的一些命令都和本地进程管理命令类似,例如:

  • 查看当前正在执行的容器:docker ps,当然如果现在执行什么都不会显示,因为我们还没有任何容器;
  • 查看当前所有容器(包括正在执行的和已经结束的):docker ps -a,同样,现在执行,我们也不会看到任何结果;
  • 查看本地已经安装的docker镜像:docker images

当然,现在你可能还还分不清楚什么是容器,什么是镜像,这很正常。接下来,我们执行:docker run ubuntu:latest ls -l执行一个ubuntu 18.04容器。第一次执行这条命令的时候,由于本地还没有ubuntu 18.04的安装镜像,因此docker会自动从Docker Hub上下载,下载完成后:

image

上图列出的目录,就是在ubuntu 18.04中执行ls -l命令的结果,这样我们就执行了自己的第一个容器。

现在,重新执行docker ps,还是什么结果都没有。但是,重新执行docker ps -a就会看到下面的结果:

image

通过这个表,可以得到下面这些信息:

首先,CONTAINER ID,这是docker给每一个容器分配的唯一ID,我们可以使用这个ID管理容器。

其次,IMAGE,这是Docker镜像的名称。所谓镜像,指的是执行Docker容器所需要的文件。它类似虚拟机的镜像文件。这里多说一句关于镜像的命名方式。在Docker Hub上可以看到,我们有很多版本的Ubuntu镜像可以使用:


-w556

例如,为了使用ubuntu 18.04,基于官方提供的这些信息,我们可以使用下面三种命令:

  • docker run ubuntu:18.04
  • docker run ubuntu:latest
  • docker run ubuntu:bionic

它们是完全一样的。理解了这种方式之后,执行其它版本的Ubuntu的方法是类似的,我们就不重复了。大家只要理解版本号的使用方法就好了。

第三,COMMAND,指的是容器执行的命令。

第四,CREATED,指的是容器的创建时间。

第五,STATUS,指的是容器的状态,从这里可以看到,它已经结束了,实际上我们创建的这个容器的生命周期非常短,就是执行ls -l这条命令的时间,命令结束了,容器也就结束了。

第六,PORTS,指的是容器的端口映射规则,等用到的时候我们再说。

最后,NAMES,它和CONTAINER ID类似,Docker生成的容器名称。

接下来,我们再执行下docker images

image

可以看到,这就是我们为了在ubuntu 18.04中执行ls -l命令要下载的文件,相比虚拟机,它可小多了。


二、容器里究竟有些什么东西

在一个容器里,究竟有哪些内容呢?为了帮助我们了解这个信息,docker提供了一个命令:docker inspect,而它就是我们这一节的主角。

这个命令需要接受一个容器ID或者NAME作为参数。因此,我们可以先执行docker ps -a,可以看到这就是我们在上一节视频中执行过的容器:

image

接下来,我们执行:docker inspect 1d6b9c71eeb9或者docker inspect priceless_hugle,就会看到类似下面这样的结果:

image

这是一个JSON对象,包含了一个容器的全部内容。当然我们没必要逐一去讲每一个字段的含义,大家在终端里执行一下,然后自己去看看就好。

1、两种访问inspect结果的方法

接下来我们要介绍的,是两种可以从这个JSON中提取信息的方法,毕竟每次都从这么大一堆东西里找内容就太不方便了。

第一种方法,是docker inspect原生支持的,它有一个-f参数,允许我们用go template的语法选择要使用的JSON字段。

例如,为了读取容器IP地址字段,我们可以这样:


image

当然,由于当前这个容器没有执行,因此我们在终端上只会看到一个空行。如果我们把IPAddress换成SandboxID就会看到结果了。

image

注意在template里,双大括号不要与中间的内容有空格

如果你觉得Go template的语法用起来并不方便,这里再向大家介绍一个工具:jq。它是一个很方便的基于命令行的JSON parser,我们直接执行brew install jq安装。完成后,执行docker inspect 1d6b9c71eeb9 | jq

image

可以看到,之前黑白的JSON结果变成彩色的了。并且,和docker inspect-f参数类似,它接受一个-r参数也可以让我们访问指定的字段,例如之前的访问IP地址,现在可以这样:

docker inspect 1d6b9c71eeb9 | jq -r ".[0].NetworkSettings.IPAddress"

也就是说,我们从根节点数组中,选取了第一个元素,然后访问了它的NetworkSettings.IPAddress节点。类似的,为了bridge网卡的IP地址,我们可以这样:

docker inspect 1d6b9c71eeb9 | jq -r ".[0].NetworkSettings.Networks.bridge.IPAddress"

大家可以在这里找到jq的官方示例,我们就不在这里重复它的具体用法了。

在我看来,相比go template的语法,jq用起来还是更自然一些。当然,它们的结果是一样的,大家只要在查看容器信息的时候,选择一种自己用的惯的,就好了。


三、清理和容器有关的资源

如果你刚开始学习docker不久,一个最常见的问题就是,在反复试验和练习中,无意间就创造大量已经执行结束的容器对象。在这一节,我们就来看和清理docker镜像和容器相关的操作。

1、如何删除容器

为了演示这个场景,我们再执行一次之前的容器:docker run ubuntu:latest ls -l。完成后,我们执行docker ps -a,就会看到下面这样的结果:

image

可以看到,我们已经有两个执行结束的容器了。当我们随意练习的时候,很容易就积累了很多无意义的容器对象。为此,我们可以执行:

docker rm 842dd8c58cbe
docker rm distracted_cray

删掉它们。同样,使用容器的ID和名字,都是可以的。或者,如果你想清空容器列表,还可以执行:

docker rm $(docker ps -a -q)

这里,-q是让docker ps命令只显示容器ID列表。我们也可以把-a -q写成-aq。这时,你可能会想,每次执行完一个容器之后还要记得删掉很麻烦啊,能不能执行完就自动删掉呢?为此,我们可以这样:

docker run --rm ubuntu:latest ls -l

再执行容器的时候添加--rm参数,就可以了。这时,如果你执行docker ps -a就看不到刚才执行过的容器了。

2、如何删除镜像

了解了如何删除容器之后,我们再来看如何删除镜像。首先,执行docker images查看下当前的镜像列表:

image

可以看到,我们下载了三个镜像。为了删掉ubuntu镜像我们可以执行:

docker rmi ubuntu:latest

这里,我们要使用name:tag的形式来指定镜像。实际上,删除镜像也可以使用镜像ID,只不过我们要用docker images -q命令来查看,然后把它组合到docker rmi就好了:

docker rmi $(docker images -q)
image

四、如何与容器交互

如何能“登录”到正在执行中的容器中看看呢?就像我们登录到虚拟机中一样。显然执行ls -l命令这样的容器很难。为了能“登录”到容器内部,我们至少得让容器执行一个稍微活的长一些的程序,例如:bash

首先,如果我们直接执行:docker run ubuntu:latest bash,就会发现,还是执行一下就退出了。然后,执行docker ps -a查看:

image

就能看到我们刚才这个容器了。为了能和容器里这个bash交互,我们需要在执行的时候,给docker传递两个命令行参数,像这样:

docker run -i -t ubuntu:latest bash

其中:

  • -i是interactive,表示我们要和容器交互;
  • -t是tty,让docker创建一个虚拟终端,这样我们就能在屏幕上看到来自容器的控制台输出了;

当我们执行之后,就会看到类似这样的结果:


-w437

这样,我们就“登录”到容器内部了。此时我们在终端中执行的命令,都是在ubuntu 18.04这个容器中执行的。这时,我们执行一下ps aux会看到这样的结果:

-w739

看到了吧,除了正在打印消息的ps aux进程外,整个容器里只有一个bash进程。这是容器区别于虚拟机最明显的一个地方,容器就像一个沙箱一样,把进程隔离在容器里,而进程本身对此却不知情,以为自己就是这个操作系统中的唯一进程。

接下来,要退出这个容器,我们只要执行exit离开bash就好了。Bash执行结束了,容器也就结束了。

image

1、恢复已经结束的容器

下次,我们再想在容器中执行bash的时候,除了使用docker run新启动一个容器之外,还可以重新启动之前退出的容器。例如,我们执行:docker start e7e7092afdc4

image

这次,从docker ps的结果,我们知道这个容器已经在运行了。但是,我们却没法和它交互。为此,我们同样要以交互模式重新启动这个容器:docker start -i e7e7092afdc4

-w368

从上面的结果中,我们知道:

  • 可以用docker stop ID停止一个在后台执行的容器;
  • 可以用-i参数以交互模式恢复容器的执行;

五、通过容器启动一个Nginx server

1、安装并启动Nginx

还是基于上一节的结果,我们以交互模式启动一个执行bash的容器:docker run -i -t ubuntu:latest bash。接下来,用起来就和普通的Ubuntu一样了,我们先在Shell中执行下面的命令安装一下Nginx:

apt-get update && apt-get install -y nginx

安装完成后,和普通的Ubuntu不同的是,Nginx不会自动启动,我们需要手工执行一下nginx命令。然后,当我们执行ps aux的时候,就会看到Nginx启动了:

image

2、通过host访问容器中的Web服务

接下来,该如何在host中访问容器中的Nginx服务呢?保持这个Nginx容器运行的条件下,我们新建一个终端,然后用之前说过的方式查看一下它的IP地址:

docker inspect e7e7092afdc4 | jq -r ".[0].NetworkSettings.IPAddress"

在我的Mac上,这个值是172.17.0.2。然后,如果我们直接请求这个地址就会发现并不能访问。道理很简答,Nginx的80端口是开放在容器内的,我们当然无法直接通过host请求到。

为此,我们得在启动容器的时候,把这个容器内的端口,映射到容器外面来。首先,执行exit从容器里退出来,然后执行下面的命令启动一个开启了端口映射的容器:

docker run -it -p 8080:80 ubuntu:latest bash

这里,-p参数可以让我们用host_port:container_port的格式指定容器内外的端口映射规则。因此,上面的命令,就是帮助我们把容器内的80端口,映射到了host上的8080端口。

但是,先别着急访问。因为我们重新执行了容器之后,这仍旧是一个执行Bash的容器,这里面并没有Nginx执行,因此,我们还得重新执行一下apt-get update && apt-get install nginx -y安装一下。完成后,执行nginx命令启动Nginx。

当然,你可能觉得每次都这么重装很麻烦。在后面的视频里,我们会讲到如何通过Dockerfile自动化容器的构建,以及保存已有修改的方法。当前我们这个例子,重点还是放在端口映射上。

现在,我们只要访问http://localhost:8080,就能请求到容器内的Nginx了。

image

六、通过Volumn共享文件

之前我们启动的Nginx容器,使用的是容器内默认的文件系统。那么,我们该如何让这个Nginx使用Host上我们指定目录中的内容呢?

当然,用某种方法把文件拷贝到容器内部算是一种方法,但是一来,这种方法并不经济;二来,让host和container保持内容的同步也不容易。最好的办法,则是可以像端口映射一样,把Host上的某个目录映射到容器里。为此,我们可以在启动容器的时候,使用-v参数。

具体怎么做呢?由于容器中的Nginx默认的web根目录是/var/www/html,最简单的,我们把这个目录映射出来就好了。

首先,在host中,创建一个/tmp/web目录,并在其中添加一个demo.html文件。这里为了演示,我们只是添加了一句话而已:

image

其次,执行下面的命令启动docker:

docker run -it -p 8080:80 -v /tmp/web:/var/www/html ubuntu:latest bash

这里,我们使用了-v host_dir:container_dir进行了目录映射。映射之后,在容器中,之前/var/www/html目录指定的内容就无法访问了。现在/var/www/html访问的,是host上的/tmp/web目录。

实际上,我们也可以用这样的方式给容器添加多个目录映射,只要使用多个-v参数就好了。

第三,在容器里指定apt-get update && apt-get install nginx -y安装nginx。

最后,在容器里,执行nginx启动。这样,容器里的Nginx就使用host上的/tmp/web作为服务器的根目录了。

我们打开浏览器,访问http://localhost:8080/demo.html,就可以看到下面的结果了:

image

相关文章

  • 四 必备Docker知识

    (一) Docker基础知识 https://hub.docker.com/[https://hub.docker...

  • Docker

    # Docker java进阶/docker 学习目标: 掌握Docker基础知识,能够理解Docker镜像与容器...

  • Docker 基础知识

    Docker 基础知识 install brew cask install docker mirror(Regis...

  • docker 入门

    Docker 学习目标: 掌握Docker基础知识,能够理解Docker镜像与容器的概念 完成Docker安装与启...

  • Docker学习笔记

    Docker 掌握Docker基础知识,理解Docker镜像与容器的概念 完成Docker安装与启动 掌握Dock...

  • Docker学习笔记

    Docker 学习目标: 掌握Docker基础知识,能够理解Docker镜像与容器的概念 完成Docker安装与启...

  • Docker集群管理基础

    这篇文章讲了Docker-machine,Docker-compose,Docker-swarm的一些基础知识。 ...

  • Gitlab 及 Gitlab Runner的搭建

    本文后续所有安装都基于 docker ,所以需要一定的 docker 基础知识储备。 Docker 的准备 卸载 ...

  • k8s日志收集实战

    基础知识 Docker 引擎日志 Docker 引擎日志 一般是交给了 Upstart(Ubuntu 14.04)...

  • Spring Boot与Docker部署

    了解Docker的一些基础知识Docker——入门实战Docker —— 从入门到实践 Centos7上安装doc...

网友评论

      本文标题:Docker 基础知识

      本文链接:https://www.haomeiwen.com/subject/emyymftx.html