docker 知识整理

134 阅读6分钟

docker 知识整理

Docker 是一个开源的应用容器引擎,可以让开发者打包他们的应用以及依赖包到一个轻量级,可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。

Docker的应用场景:

web应用的自动化打包和发布

自动化测试和持续集成。发布

在服务型环境中部署和调整数据库或其他的后台应用

从头编译或者扩展现有的OpenShift 或 Cloud Foundry平台来搭建自己的PaaS环境。

Docker 的优点:

1.快速,一致的交付你的应用程序

2.响应式部署和扩展

3.在同一硬件上运行更多的工作负载

Docker 镜像:

Docker镜像是用于创建Docker容器模板

Docker 容器:

容器时独立运行的一个或一组应用,是镜像运行时的实体

Docker 客户端:

Docker客户端同过命令行或者其他工具使用与docker的守护进程通信。

Docker主机:

一个物理或者虚拟的机器用于执行Docker守护进程和容器

1.使用docker run命令来在容器内运行一个应用程序

docekr run ubuntu:15.10 /bin/echo "Hello world"

docker run - i -t ubuntu:15.10 /bin/bash

-t:在新容器内指定一个伪终端或终端。 -i:允许你对容器内的标准输入进行交互。

exit:命令或者CTRL+D来退出容器

通过ID来查看对应的容器发生了什么。

docker ps 来查看

runoob@runoob:~$ docker ps
CONTAINER ID        IMAGE                  COMMAND              ...  
5917eac21c36        ubuntu:15.10           "/bin/sh -c 'while t…"    ...

输出详情介绍:

CONTAINER ID:容器ID。

IMAGE:使用的镜像

COMMAND:启动容器时运行的命令

CREATED:容器的创建时间

STATUS:容器状态

状态有7种:

created (已创建)

restarting(重启中)

running或up(运行中)

removing(迁移中)

paused(暂停)

exited(停止 )

dead(死亡)

POPTS:容器的端口信息和使用的连接类型

Names:自动分配的容器名称

停止容器

docker stop 命令来停止容器

Docker 客户端

docker命令可以产看到Docker客户端的所有命令选项

docker command --help 更深入的了解指定的Docker 命令使用

启动容器

使用命令ubuntu镜像启动一个容器,参数为以命令行模式进去该容器

docker run -it ubuntu /bin/bash

-i 交互式操作

-t 终端

ubuntu: ubuntu镜像。

/bin/bash:放在镜像后的是命令,这里我们希望有个交互式Shell,因此用的是/bin/bash.

使用 docker start 启动一个已停止的容器:

docker start b750bbbcfd88 

重启容器

docker restart <容器 ID>

进入容器

在使用 -d 参数时,容器启动后会进入后台。此时想要进入容器

docker exec -it 243c32535da7 /bin/bash

image.png

导出和导入容器

导出容器:

如果要导出本地某个容器,可以使用docker export 命令。

 docker export 1e560fca3906 > ubuntu.tar

导出容器 1e560fca3906 快照到本地文件 ubuntu.tar。

image.png

导入容器快照

可以使用 docker import 从容器快照文件中再导入为镜像,以下实例将快照文件 ubuntu.tar 导入到镜像 test/ubuntu:v1:

cat docker/ubuntu.tar | docker import - test/ubuntu:v1

image.png

此外,也可以通过指定 URL 或者某个目录来导入,例如:

docker import http://example.com/exampleimage.tgz example/imagerepo

删除容器

docker rm -f 1e560fca3906

image.png

下面的命令可以清理掉所有处于终止状态的容器。

$ docker container prune

运行一个web应用

docker run -d -p training/webapp python app.py

-d:让容器在后台运行

-P:将容器内部使用的网络端口随机映射到我们使用的主机上

使用docker ps 来查看我们正在运行的容器

runoob@runoob:~#  docker ps
CONTAINER ID        IMAGE               COMMAND             ...        PORTS                 
d3d5e39ed9d3        training/webapp     "python app.py"     ...        0.0.0.0:32769->5000/tcp

这里多了端口信息

PORTS
0.0.0.0:32769->5000/tcp

Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 32769 上。

这时我们可以通过浏览器访问WEB应用

网络端口的快捷方式:

docker还提供了另一个快捷方式docker port,使用docker port 可以查看指定(ID 或者名字)容器的某个确定端口映射到宿主机的端口号。

docker port bf8b7f2cd99 或者docker port wizardly_chandrasekhar 来查看容器端口的映射情况。

runoob@runoob:~$ docker port bf08b7f2cd89
5000/tcp -> 0.0.0.0:5000
runoob@runoob:~$ docker port wizardly_chandrasekhar
5000/tcp -> 0.0.0.0:5000

查看WEB 应用程序日志

docker logs [ID或者名字] 可以查看容器内部的标准输出

runoob@runoob:~$ docker logs -f bf08b7f2cd89
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
192.168.239.1 - - [09/May/2016 16:30:37] "GET / HTTP/1.1" 200 -
192.168.239.1 - - [09/May/2016 16:30:37] "GET /favicon.ico HTTP/1.1" 404 -

-f :让docker logs 像使用tail -f 一样来输出容器内部的标准输出。 从上面,我们可以看到应用程序使用的是 5000 端口并且能够查看到应用程序的访问日志。

查看WEB应用程序容器的进程

我们还可以使用docker top来查看容器内部运行进程

docker top wizardly_chandrasekhar

停止 WEB 应用容器

runoob@runoob:~$ docker stop wizardly_chandrasekhar   
wizardly_chandrasekhar

重启WEB应用容器

已经停止的容器,我们可以使用命令 docker start 来启动。

runoob@runoob:~$ docker start wizardly_chandrasekhar
wizardly_chandrasekhar

docker ps -l 查询最后一次创建的容器:

#  docker ps -l 
CONTAINER ID        IMAGE                             PORTS                     NAMES
bf08b7f2cd89        training/webapp     ...        0.0.0.0:5000->5000/tcp    wizardly_chandrasekhar

移除WEB应用容器

runoob@runoob:~$ docker rm wizardly_chandrasekhar  
wizardly_chandrasekhar

删除容器时,容器必须是停止状态,否则会报如下错误

列出镜像列表

docker images

runoob@runoob:~$ docker images           
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              14.04               90d5884b1ee0        5 days ago          188 MB
php                 5.6                 f40e9e0f10c8        9 days ago          444.8 MB
nginx               latest              6f8d099c3adc        12 days ago         182.7 MB
mysql               5.6                 f2e8d6c772c0        3 weeks ago         324.6 MB
httpd               latest              02ef73cf1bc0        3 weeks ago         194.4 MB
ubuntu              15.10               4e3b13c8a266        4 weeks ago         136.3 MB
hello-world         latest              690ed74de00f        6 months ago        960 B
training/webapp     latest              6fae60ef3446        11 months ago       348.8 MB
  • REPOSITORY: 表示镜像的仓库源
  • TAG: 镜像的标签
  • IMAGE ID: 镜像ID
  • CREATED: 镜像创建时间
  • SIZE: 镜像大小

获取一个新镜像

docker pull 命令来下载它。

查找镜像

docker search 搜索镜像。(需要搜素httpd的镜像来作为我们的web服务)

docker search httpd

拖取镜像

docker pull

创建镜像

更新镜像之前,我们需要使用镜像来创建一个容器。

当docker镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过一下两种方式进行对镜像进行更改

  1. 从已经创建的容器中更新镜像,并且提交这个镜像
  2. 使用Dockerfile指令来创建一个新的镜像
~ $ docker run -t -i ubuntu:15.10 /bin/bash

e218edb10161:/#

在运行的容器内使用apt -get update 命令进行更新

在完成操作后,输入exit命令来退出这个容器

此时 ID 为 e218edb10161 的容器,是按我们的需求更改的容器。我们可以通过命令 docker commit 来提交容器副本。

构建镜像

docker build 从零开始来创建一个新的镜像,为此,我们需要创建一个Dockerfile文件,其中包含一组指令来告诉

Docker如何构建我们的镜像。

root@root:~$ cat Dockerfile 
FROM    centos:6.7
MAINTAINER      Fisher "fisher@sudops.com"

RUN     /bin/echo 'root:123456' |chpasswd
RUN     useradd runoob
RUN     /bin/echo 'runoob:123456' |chpasswd
RUN     /bin/echo -e "LANG="en_US.UTF-8"" >/etc/default/local
EXPOSE  22
EXPOSE  80
CMD     /usr/sbin/sshd -D

每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。

第一条FROM,指定使用哪个镜像源

RUN 指令告诉docker在镜像内执行命令,安装了什么。。。

然后,使用我们Dockerfile 文件,通过build 命令来构建一个镜像。

$ docker build -t runoob/centos:6.7 .

-t 指定要创建的目标镜像名

. :Dockerfile 文件所在目录,可以指定Dockerfile的绝对路径

使用docker images 查看创建的镜像已经在列表中存在,镜像ID为860c279d2fec

run@run:~$ docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED              SIZE
runoob/centos       6.7                 860c279d2fec        About a minute ago   190.6 MB
runoob/ubuntu       v2                  70bf1840fd7c        17 hours ago         158.5 MB
ubuntu              14.04               90d5884b1ee0        6 days ago           188 MB
php                 5.6                 f40e9e0f10c8        10 days ago          444.8 MB
nginx               latest              6f8d099c3adc        12 days ago          182.7 MB
mysql               5.6                 f2e8d6c772c0        3 weeks ago          324.6 MB
httpd               latest              02ef73cf1bc0        3 weeks ago          194.4 MB
ubuntu              15.10               4e3b13c8a266        5 weeks ago          136.3 MB
hello-world         latest              690ed74de00f        6 months ago         960 B
centos              6.7                 d95b5ca17cc3        6 months ago         190.6 MB
training/webapp     latest              6fae60ef3446        12 months ago        348.8 MB

docker tag 命令详解

作用

给本地镜像打一个标记(tag),可将其归入某一个仓库

有点像 Git里面给不同时段写的代码打不同的tag

语法格式:

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

实际例子

docker tag docker tag jenkins/poloyy:latest poloyy/jenkins:new2

image.png

实际使用场景

  • 当镜像配置到一定程度时,想打个 tag 进行记录当前版本,可以打个 V1
  • 再次更新镜像时,又可以打个 V2
  • 当是最新版本待上传时,可以不打默认就是 latest 最新
  • 这样不仅能保存最新版本的镜像,也能保存历史版本的镜像,方便新版本镜像出问题时进行版本回溯

image.png

Docker 容器互联

端口映射并不是唯一把 docker 连接到另一个容器的方法。

docker 有一个连接系统允许将多个容器连接在一起,共享连接信息。

docker 连接会创建一个父子关系,其中父容器可以看到子容器的信息

新建网络

$ docker network create -d bridge test-net

查看容器网络列表

docker network create -d bridge test-net

image.png

-d: 参数指定Docker网络类型, 有bridge overlay

连接容器

运行一个容器并连接到新建的test-net 网络

$ docker run -itd --name test1 --network test-net ubuntu /bin/bash

打开新的终端,在运行一个容器并加入到test-net 网络

$ docker run -itd --name test2 --network test-net ubuntu /bin/bash

image.png 通过ping验证test1容器和test2容器建立的互联关系

在test1容器中执行命令

先进入容器

docker exec -it test1 /bin/bash

ranhou ping test2

image.png

test2同理

Docker Dockerfile

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

FORM:定值的镜像都给予FROM的镜像,这里的nginx就是定制需要的基础镜像,后续的操作都基于nginx RUN:用于执行后面耕者的命令行命令。有以下两种格式

RUN <命令行命令>
# <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式:

RUN ["可执行文件", "参数1", "参数2"]
# 例如:
# RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

以 && 符号连接命令,这样执行后,只会创建 1 层镜像。

FROM centos\
RUN yum -y install wget \\
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \\
    && tar -xvf redis.tar.gz

指令详解

COPY

复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

格式:

COPY [--chown=<user>:<group>] <源路径1>...  <目标路径>
COPY [--chown=<user>:<group>] ["<源路径1>",...  "<目标路径>"]

[-- chown= < user > :< group >] :可选参数,用户改变复制到容器内文件的拥有者和属组。

<目标路径> :容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。

ADD

ADD 指令和COPY的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

ADD的优点:在执行为tar压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。

CMD

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。

格式:

CMD <shell 命令> 
CMD ["<可执行文件或命令>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...]  # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数

ENTRYPOINT

类似于CMD指令,但不会被docker run 的命令行参数指定的指令所覆盖,但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。

注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。

格式:

ENTRYPOINT ["<executeable>","<param1>","<param2>",...]

假设已通过DockerFile构建了nginx:test镜像

FROM nginx

ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参 

1.不传参运行

$ docker run  nginx:test

2.传参运行

$ docker run  nginx:test -c /etc/nginx/new.conf

容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)

nginx -c /etc/nginx/new.conf

ENV

设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。

格式:

ENV NODE_VERSION 7.2.0

RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
  && curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"

设置 NODE_VERSION = 7.2.0,在后续的指令中可以通过¥NODE_VERSION引用

EXPOSE

声明端口

作用:帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射

在运行时使用随机端口映射,也就是docker run-P 时,会自动随机映射 EXPOSE的端口

EXPOSE <端口1> [<端口2>...]

USER

用于指定执行后续命令的用户和用户组,这只是切换后续命零执行的用户

USER <用户名>[:<用户组>]

LABEL

LABEL 指令用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:

LABEL <key>=<value> <key>=<value> <key>=<value> ...