初识Docker


安装

Ubuntu Docker 安装

CentOS Docker 安装

Windows Docker 安装

MacOS Docker 安装

这里我的电脑是mac,采用brew安装,安装完毕记得更换国内的docker镜像源哦.

安装完毕,就开始使用,一探docker的神秘了.

开始之前先看一张图:现在看不懂没关系,之后我会解释

初识Docker

Image 文件

Docker把应用程序及其依赖打包在一个image文件里面,可以理解为一个容器的说明书. 通过这个image文件可以生成容器的实例.同一个image文件可以生成同时运行的多个实例.

image文件是一个二进制文件,实际上,一个image文件往往继承自另外一个image文件,加上一些个性化设置而成.举例来说:你可以在ubuntu的image基础上加上Apache服务器,形成你自己的image.

# 列出本机的所有 image 文件。
$ docker image ls

删除 image 文件

$ docker image rm [imageName]

并且image文件是通用的,一台机器上的image文件拷贝到另一台机器上,照样可以使用.一般来说,我们往往是使用别人制定好的image文件,及时要定制,也可以对已有的image文件进行加工,而不是从头制作,这样可以节省很多时间.

为了方便,image制作完成后,可以上传到网上的仓库,Docker 的官方仓库 https://hub.docker.com/ 是最重要、最常用的 image 仓库。此外,出售自己制作的 image 文件也是可以的。

实例: Hello world

下面,我们通过最简单的 image 文件"hello world",感受一下 Docker。

首先,运行下面的命令,将 image 文件从仓库抓取到本地。

$ docker image pull library/hello-world

上面的代码中,docker image pull 是抓取image文件的命令,library/hello-world是image文件在仓库里面的位置,其中library是image文件所在的组,hello-world是image文件的名字.

由于Docker官方提供的文件都放在library组里面,所以他是默认组,可以省略.因此上面的命令可以写成下面这样:

$ docker image pull hello-world

抓取成功后就可以看到本地的image文件了,

ig:~ itguang$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              e38bc07ac18e        3 weeks ago         1.85kB

现在运行这个image文件,可以看到如些输出:

ig:~ itguang$ docker container run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/
For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/

docker container run 会从一个镜像文件中生成一个容器实例,并且运行它.注意,docker container run命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件,就会从仓库自动抓取。因此,前面的docker image pull命令并不是必需的步骤。

待上面那段提示输出后,hello-world就会停止运行,容器就会终止.

有些容器不会终止,因为提供的是服务,比如安装unbuntu的image,就可以在命令行体验unbutu系统.

对于那些不会自动终止的容器,必须使用docker container kill [container_id]来终止.
我们可以新打开一个终端窗口:

ig:~ itguang$ docker container ls  # 查看当前运行容器
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
649a6b785a86        ubuntu              "bash"              3 seconds ago       Up 4 seconds                            loving_austin
ig:~ itguang$ docker container kill 649a6b785a86 # 杀死某个容器
649a6b785a86
ig:~ itguang$ docker container ls 再次查看
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
ig:~ itguang$

container 容器文件

**image文件生成的实例本身也是一个文件,成为容器文件.**也即是说,一旦容器生成,就会存在两个文件:一个image文件,一个容器文件.而且关闭容器并不会删除容器文件,只是容器停止运行而已.

# 列出本机正在运行的容器
$ docker container ls

列出本机所有容器,包括终止运行的容器

ig:~ itguang$ docker container ls --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
649a6b785a86 ubuntu "bash" 10 minutes ago Exited (137) 9 minutes ago loving_austin
85b9c705e73f hello-world "/hello" 10 minutes ago Exited (0) 10 minutes ago silly_lumiere
c9281ad7f7b8 ubuntu "bash" 17 minutes ago Exited (127) 11 minutes ago stupefied_curran
e06bf36259ef hello-world "/hello" 24 minutes ago Exited (0) 24 minutes ago flamboyant_chaplygin
ig:~ itguang$

可以看出,我现在已经有了四个容器,终止运行的容器文件依然会占用硬盘空间,可以使用docker container rm [container_id]命令删除.

ig:~ itguang$ docker container ls --all
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                        PORTS               NAMES
c9281ad7f7b8        ubuntu              "bash"              22 minutes ago      Exited (127) 17 minutes ago                       stupefied_curran
e06bf36259ef        hello-world         "/hello"            29 minutes ago      Exited (0) 29 minutes ago                         flamboyant_chaplygin
ig:~ itguang$ docker container rm c9281ad7f7b8 e06bf36259ef

Dockerfile 文件

学会了如何使用image文件和生成容器文件之后,接下来你可能会想直到这个image文件是如何生成的呢?如果你要推广自己的软件,势必要制作自己的image文件.

这时候就要用到Dockerfile文件,他是一个文本文件,用来配置image.Docker容器根据Dockerfile文件生成image二进制文件.

下面通过一个实例,来演示如何编写Dockerfile文件生成自己的image二进制文件.

实例:制作自己的 Docker 容器

下面我以 koa-demos 项目为例,介绍怎么写 Dockerfile 文件,实现让用户在 Docker 容器里面运行 Koa 框架。

  • 1.先下载源代码:
$ git clone https://github.com/ruanyf/koa-demos.git
$ cd koa-demos
  • 2.编写 Dockerfile 文件

首先,在项目的根目录下,新建一个文本文件.dockerignore,写入下面的内容。

.git
node_modules
npm-debug.log

上面的代码表示,这三个路径要排除,不要打包进image文件,如果你没有路径可以排除,这个文件也可以不用建立.

然后在项目根目录下再新建一个Dockerfile文本文件,写入下面的内容:

FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000

上面代码解释如下:

From node:8.4 : 该image继承自官方的node image,冒号表示标签,这里表示8.4,即8.4版本的node.

COPY . /app :将当前目录下的所有文件都拷贝到image文件的 /app 目录.

WORKDIR /app : 指定接下来的工作目录为 /app .

RUN npm install:在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。

EXPOSE 3000 : 将容器的3000 端口暴露出来,允许外部连接这个端口.

  • 创建 image 文件.

有了 Dockerfile文件以后就可以使用 docker image build 命令创建image文件了.

$ docker image build -t koa-demo .
# 或者
$ docker image build -t koa-demo:0.0.1 .

上面代码中,-t参数用来指定image文件的名字,后面还可以用冒号指定标签,如果不指定,默认标签就是latest,最后那个.表示Dockerfile文件所在的路径.这个例子Dockerfile文件在当前路径,所以就是一个.

如果构建成功,会有如下提示信息:

...
Successfully built 979e0930e4b6
Successfully tagged koa-demo:latest

我们使用docker images 查看当前的image文件

ig:koa-demos itguang$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
koa-demo            latest              979e0930e4b6        About a minute ago   676MB
ubuntu              latest              452a96d81c30        8 days ago           79.6MB
hello-world         latest              e38bc07ac18e        3 weeks ago          1.85kB
node                8.4                 386940f92d24        8 months ago         673MB

  • 生成容器

前面讲过,docker container run 命令会从image文件生成容器,

$ docker container run -p 8000:3000 -it koa-demo /bin/bash
# 或者
$ docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash

上面各个参数解释如下:

-p : 容器的3000端口映射到本地的8000端口.

-it : 容器的shell会映射到当前本地的shell,你在本机窗口输入的命令会传入到容器中.

koa-demo:0.0.1 :image 文件的名字(如果有标签,还需要提供标签,默认是 latest 标签)。

/bin/bash : 容器启动以后,容器内部第一个执行的命令.这里是启用Bash,以保证用户可以使用shell

如果一切正常,运行上面的命令以后,就会返回一个命令行提示符。

root@6be4c4a279df:/app#

这表示你已经在容器里面了,返回的提示符就是容器内部的 Shell 提示符。执行下面的命令。

root@6be4c4a279df:/app# node demos/01.js

这时,Koa 框架已经运行起来了。打开本机的浏览器,访问 http://127.0.0.1:8000,网页显示"Not Found",这是因为这个 demo 没有写路由。

这个例子中node进程运行在Docker容器的虚拟环境里面,进程接触到的文件系统和网络接口都是虚拟的,与本机文件系统和网络接口都是隔离的,因此需要定义容器与物理机的端口映射(map).

现在,在容器的命令行下,按ctrl+c停止node进程,按ctrl+d(或者exit)退出容器.此外,也可以使用docker container kill [container-id]终止容器的运行.

# 在本机的另一个终端窗口,查出容器的 ID
$ docker container ls

停止指定的容器运行

$ docker container kill [containerID]

也可以使用docker container run 命令的 --rm 参数,在容器终止运行后自动删除容器文件.

$ docker container run --rm -p 8000:3000 -it koa-demo /bin/bash

CMD 命令

上一节的例子里面,容器启动以后,需要手动输入命令node demos/01.js。我们可以把这个命令写在 Dockerfile 里面,这样容器启动以后,这个命令就已经执行了,不用再手动输入了。

FROM node:8.4
COPY . /app
WORKDIR /app
RUN npm install --registry=https://registry.npm.taobao.org
EXPOSE 3000
CMD node demos/01.js

上面的Dockerfile文件最后面多了一行CMD node demos/01.js,表示容器启动后,自动执行node demos/01.js.

你可能会问RUN 命令和 CMD 命令的区别是什么呢?

简单来说:RUN命令在image文件的构建阶段执行,执行结果会打包进image文件;CMD命令则是在容器启动后执行.另外一个Dockerfile文件只能包含多个RUN命令,但只能包含一个CMD命令,

注意:制定了CMD命令后,docker container run命令就不能附加命令了,比如前面的/bin/bash,否则,它会覆盖CMD命令

现在启动容器可以用下面的命令:

$ docker container run --rm -p 8000:3000 -it koa-demo:0.0.1

发布image文件

容器运行成功后,就确认了image文件的有效性,这是我们就可以考虑把image文件分享到网上.
首先,去 hub.docker.com 或 cloud.docker.com注册一个账户。然后,用下面的命令登录。

$ docker login

接着,为本地的 image 标注用户名和版本。

$ docker image tag [imageName] [username]/[repository]:[tag]
# 实例
$ docker image tag koa-demos:0.0.1 ruanyf/koa-demos:0.0.1

也可以不标注用户名,重新构建一下 image 文件。

$ docker image build -t [username]/[repository]:[tag] .

最后,发布 image 文件。

$ docker image push [username]/[repository]:[tag]

发布成功以后,登录 hub.docker.com,就可以看到已经发布的 image 文件。

其他有用的命令

docker的主要用法就是上面这些,另外还有一些常见的命令:

  • docker container start
    前面的docker container run命令是新建容器,每运行一次,就会新建一个容器.同样的命令运行两次就会生成两个一模一样的容器文件.如果希望重复使用容器,就需要使用docker container start命令,它用来启动已经生成,已经停止运行的容器文件.
$ docker container start [container_id]
  • docker container stop

前面的docker container kill命令终止容器的运行,相当于向容器的主进程发送SIGKILL信号,而docker container stop也是用来终止容器的运行,相当于向容器的主进程发送SIGTERM信号,然后过一段时间在发送SIGKILL信号.

$ docker container stop [container_id]

这个信号的差别就是,程序收到SIGTERM信号后,可自行进行收尾清理工作,但也可以不理会这个信号;但如果收到SIGKILL信号,就会立即终止这个容器的运行,那些正在进行的操作会全部丢失

  • docker container logs

docker container logs用来查看容器的输出,即容器里shell的标准输出.比如: 如果docker run命令运行容器的时候,没有使用-it参数,就要使用这个命令查看输出.

$ docker container logs [container_id]
  • docker container exec

docker container exec命令用于进行一个正在运行的容器.如果docker container run命令运行容器的时候,没有使用-it参数,就要使用这个命令进入进入容器,一旦进入容器,就可以在容器的shell执行命令了.

$ docker container exec [container_id] /bin/bash
  • docker container cp

docker container cp命令用于从正在运行的容器里,将文件拷贝到本机.下面是拷贝当前 目录的写法:

$ docker container cp [container_id]:[/path/to/file] .

总结

到了这里相信你对docker的基本操作与相关概念已经有了大概了解,现在让我们回到文章开头的那个图:

初识Docker

可以看出: Dockerfile,Docker hub,image镜像文件,container容器文件,容器实例 的关系一目了然.

  • image文件来源有两个:Dockfile文件和Docker hub.
  • 可以使用docker container run命令从image文件生成并运行容器.

关于docker常用命令我在这里进行了详细总结:

docker常用命令总结

上一篇:python-ldap 简单试用


下一篇:NGINX速率限制原理及源码分析