初学docker

Posted by 畅通 on March 3, 0208

环境配置问题

软件开发最大的麻烦事之一,就是环境配置。举例来说,安装一个 Python 应用,计算机必须有 P ython 引擎,还必须有各种依赖,可能还要配置环境变量。

解决上述问题的方案有很多种,分配一台物理机,虚拟机,如果这些系统挂掉了,意味着时时刻刻面临着 重新做系统等的风险,然后对系统重新部署、代码、配置重新部署的风险,间接上增加了很多运维工作的 内容。

Linux 容器

鉴于以上风险,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。

Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。或者说,在正常进程的外面套了 一个保护层。对于容器里面的进程来说,它接触到的各种资源都是虚拟的,从而实现与底层系统的隔离。 由于容器是进程级别的,相比虚拟机有很多优势。

    它具有以下优点:
  • (1)启动快 容器里面的应用,直接就是底层系统的一个进程,而不是虚拟机内部的进程。所以,启动容器相当于 启动本机的一个进程,而不是启动一个操作系统,速度就快很多;
  • (2)资源占用少 容器只占用需要的资源,不占用那些没有用到的资源;虚拟机由于是完整的操作系统,不可避免要占用 所有资源。另外,多个容器可以共享资源,虚拟机都是独享资源;
  • (3)体积小 容器只要包含用到的组件即可,而虚拟机是整个操作系统的打包,所以容器文件比虚拟机文件要小很多。
  • 总之,容器有点像轻量级的虚拟机,能够提供虚拟化的环境,但是成本开销小得多。

什么是DOCKER

Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。它是目前最流行的 Linux 容 器解决方案。

Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。 程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。

DOCKER的用途

    Docker 的主要用途,目前有三大类。
  • (1)提供一次性的环境。比如,本地测试他人的软件、持续集成的时候提供单元测试和构建的环境。
  • (2)提供弹性的云服务。因为 Docker 容器可以随开随关,很适合动态扩容和缩容。
  • (3)组建微服务架构。通过多个容器,一台机器可以跑多个服务,因此在本机就可以模拟出微服务架构。

DOCKER的安装

官方的安装地址是点我

安装完成后,可以在命令行输入 docker version 或 docker info来查看docker是否安装正常.

这里强调一下,docker安装完成后是一个客户端的,启动客户端表示已经运行起来,刚才找了半天没找到怎么 启动,如果未启动,会报如下的错误: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docke r daemon running?

image文件

Docker 把应用程序及其依赖,打包在 image 文件里面。只有通过这个文件,才能生成 Docker 容器。ima ge 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多 个同时运行的容器实例。

image 是二进制文件。实际开发中,一个 image 文件往往通过继承另一个 image 文件,加上一些个性化设 置而生成。举例来说,你可以在 Ubuntu 的 image 基础上,往里面加入 Apache 服务器,形成你的 image。

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

# 删除 image 文件 $ docker image rm [imageName]

image文件类似exe执行文件一样,可以拷贝到任意安装docker的机器上执行。为了节省时间,尽量使用别人 已经制作好的image文件,以便节省时间。运行下面的命令执行hello-world这个镜像:

docker image pull library/hello-world

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

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

docker image pull hello-world

抓取完成后,运行下面的命令就可以看到了:

docker image ls

  • REPOSITORY TAG IMAGE ID CREATED SIZE
  • hello-world latest f2a91732366c 3 months ago 1.85kB
输入下面的命令,即可运行这个IMAGE

docker container run hello-world

docker container run命令会从 image 文件,生成一个正在运行的容器实例。

注意,docker container run命令具有自动抓取 image 文件的功能。如果发现本地没有指定的 image 文件, 就会从仓库自动抓取。因此,前面的docker image pull命令并不是必需的步骤。

执行成功后,会输出这样的语句:

  • docker container run hello-world
  • Hello from Docker!
  • This message shows that your installation appears to be working correctly.

有些镜像是自动结束的,有些不是,需要手动的去删除,下面是查看镜像运行状态的命令:

  • docker ps 或者 docker container ls 或者 docker container ls --all
  • 主要有些参数要说一下
  • 1. 不加参数,表示查看当前正在运行的容器
  • 2. -a,查看所有容器包括停止状态的容器
  • 3. -l,查看最新创建的容器
  • 4. -n=x,查看最后创建的x个容器

主要返回以下几个字段信息:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ,他们分别代表如下意思:

  • CONTAINER ID:容器ID,唯一标识容器
  • IMAGE:创建容器时所用的镜像
  • COMMAND:在容器最后运行的命令
  • CREATED:容器创建的时间
  • STATUS:容器的状态(你会看到UPXXX,表示运行状态)
  • PORTS:对外开放的端口号
  • NAMES:容器名(也具有唯一性,docker是不允许创建容器名相同的容器的)

对于那些还在运行的容器,可以通过以下命令:

docker stop container id/容器名称 或者 docker kill container id

而这个docker stop命令是给容器进程发送一个SIGTERM信号(可捕捉),默认行为是容器退出。 如果要强行停止一个容器的话,最好用docker kill命令,它是发送一个SIGKILL信号(不可捕捉)

容器文件

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

终止运行的容器文件,依然会占据硬盘空间,可以使用docker container rm命令删除 ,再使用 docker container ls --all命令,就会发现被删除的容器文件已经消失了。

DockerFile文件

学会使用 image 文件以后,接下来的问题就是,如何可以生成 image 文件?如果你要推广自己的软件,势必要自己 制作 image 文件。

这就需要用到 Dockerfile 文件。它是一个文本文件,用来配置 image。Docker 根据 该文件生成二进制的 i mage 文件。

下面通过一个实例,演示如何编写 Dockerfile 文件。

制作自己的Docker文件

下面以阮一峰老师的实例,介绍怎么运用DockerFile文件,实现用户使用DNode的koa框架

  • 框架源码
  • $ git clone https://github.com/ruanyf/koa-demos.git
  • $ cd koa-demos

git下来代码后,进入文件夹,开始编写dockignore(忽略路径)和dockerfile文件

.dockerignore文件,表示需要排除的路径

  • .git
  • node_modules
  • npm-debug.log

dockerfile文件,一共五行,具体意义如下

  • FROM node:8.4:该 image 文件继承官方的 node image,冒号表示标签,这里标签是8.4,即8.4版本的 node
  • COPY . /app:将当前目录下的所有文件(除了.dockerignore排除的路径),都拷贝进入 image 文件的/app目录。
  • WORKDIR /app:指定接下来的工作路径为/app。
  • RUN npm install:在/app目录下,运行npm install命令安装依赖。注意,安装后所有的依赖,都将打包进入 image 文件。
  • EXPOSE 3000:将容器 3000 端口暴露出来, 允许外部连接这个端口。

下面是具体docker image bulid的api指令:

  • FROM 是作为镜像的基础
  • RUN 可以理解为在FROM下来的镜像做一些环境的部署。
  • CMD 是创建容器后,会运行的命令
  • EXPOSE 是暴露的端口
  • MAINTAINER 通知的邮件
  • ADD 相当于把主机的start.sh脚本传递给了容器里面。
  • VOLUME 是本地的路径的映射
  • WORKDIR 是执行的路径,也就是cmd entrypoint执行的路径。

执行命令,"sudo docker image build -t koa-demo /Users/MacBook/Downloads/koa-demos",后面最好跟上项目路径。

经过对包和依赖的下载完毕后,出现以下信息,表示生成DockerFile成功:

  • Successfully built eebb9f8541e7
  • Successfully tagged koa-demo:latest

此处有一处需要特别注意,在生成dockerfile时,如果没加国内的镜像,速度会非常慢,因为 https://hub.docker.com/的访问 非常慢,建议换成国内的镜像,类似npm功能一样,推荐https://docker.mirrors.ustc.edu.cn(中国科学技术大学)的镜像,MacOs 在docker客户端的设置->daemon->registry mirror中添加,重启即可,速度非常快,其他系统可修改配置文件,在daemon.json中 添加{"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"]}即可,具体参考:http://blog.csdn.net/small _to_large/article/details/77334973

在dockerfile生成完毕之后,通过docker image ls指令即可查看目前存在的镜像文件.

生成容器

生成容器通过一下命令

  • 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@66d80f4aaf1e:/app#

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

运行node demo/01.js,此时koa框架已经启动起来了。浏览器输入:http://127.0.0.1:8000 即可访问,访问报404错误,是因为这个页面没写路由(route)

现在,在容器的命令行,按下 Ctrl + c 停止 Node 进程,然后按下 Ctrl + d (或者输入 exit)退出容器。此外,也可以用 docker container kill终止容器运行。

查看和停止的命令不做说明了,上面已写的很清楚,下面我们说下如何删除容器文件.

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

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

CMD命令

上面的例子,我们发现启动容器后需要手动输入node demo/01.js 这个命令,我们在生成dockerfile文件时,也可以对将CMD (上面已阐述)API加入到生成语句中,这点类似NPM打包时的package.json中的run脚本,表示成功后执行那个脚本文件。

你可能会问,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 login$ 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 container logs

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

$ docker container logs [containerID]

docker container exec

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

$ docker container exec -it [containerID] /bin/bash

ocker container cp

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

$ docker container cp [containID]:[/path/to/file]

以上是docker的基本用法,下一篇一起来看具体用法