Docker
常用命令直接跳至”Docker的常用命令”
查询常用命令直接跳至”Docker的常用命令”
配置阿里云镜像:
yum-config-manager –add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
前面章节为官方文档翻译 后面为常用操作和自启设置
Docker
是什么?
系统平滑移植,容器虚拟化技术
Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。
Docker 自开源后受到广泛的关注和讨论,以至于 dotCloud 公司后来都改名为 Docker Inc。Redhat 已经在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 产品中广泛应用。
Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器(LXC)等技术。
在 LXC 的基础上 Docker 进行了进一步的封装,让用户不需要去关心容器的管理,使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。
下面的图片比较了 Docker 和传统虚拟化方式的不同之处,可见容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,而传统方式则是在硬件层面实现。
应用场景
- web应用的自动化打包和发布;
- 自动化测试和持续集成、发布;
- 在服务型环境中部署和调整数据库或其他的后台应用;
- 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。
在任何地方开发、部署和运行任何应用
Docker是一款针对程序开发人员和系统管理员来开发、部署、运行应用的一款虚拟化平台。Docker 可以让你像使用集装箱一样快速的组合成应用,并且可以像运输标准集装箱一样,尽可能的屏蔽代码层面的差异。Docker 会尽可能的缩短从代码测试到产品部署的时间。
Docker 组件
- The Docker Engine – Docker Engine 是一个基于虚拟化技术的轻量级并且功能强大的开源容器引擎管理工具。它可以将不同的 work flow 组合起来构建成你的应用。
- Docker Hub 可以分享和管理你的images镜像的一个 Saas 服务。
为什么选择Docker
快速交付应用程序
- 我们希望你的开发环境能够更好的提高你的工作效率。Docker容器能够帮助开发人员、系统管理员、QA和版本控制工程师在一个生产环节中一起协同工作。我们制定了一套容器标准,而这套容器标准能够使系统管理员更改容器的时候,程序员不需要关心容器的变化,而更专注自己的应用程序代码。从而隔离开了开发和管理,简化了开发和部署的成本。
- 我们使应用的构建方式更加简单,可以快速的迭代你的应用,并且可以可视化的来查看应用的细微更改。这能够帮助组织里边的成员来更好的理解一个应用从构建到运行的过程。
- Docker 是一个轻量级的容器,所以它的速度是非常快的,而容器的启动时间只需要一秒钟,从而大大的减少了开发、测试和部署的时间。轻松部署和扩展
- Docker 容器可以运行在大多数的环境中,你可以在桌面环境、物理主机、虚拟主机再到数据中,私有或者公有云中部署。
- 因为 Docker 可以从多平台下运行。你可以很容器的迁移你的应用程序。如果需要,你可以非常简单的将应用程序从测试环境迁移到云,或者从云迁移到测试环境。
- Docker 是一个轻量级的容器,因此它可以在很短的时间内启动和关闭。当你需要的时候,你可以启动多个容器引擎,并且在不需要使用他们的时候,可以将他们全部关闭。
Docker的容器本身不需要额外创建虚拟机管理系统,因此你可以启动多套Docker容器,这样就可以充分发挥主机服务器的物理资源,也可以降低因为采购服务器licenses而带来的额外成本。
快速构建 轻松管理
因为Docker上述轻便,快速的特性。可以使您的应用达到快速迭代的目的。每次小的变更,马上就可以看到效果。而不用将若干个小变更积攒到一定程度再变更。每次变更一小部分其实是一种非常安全的方式。
Image镜像
介绍
在 Docker 的术语里,一个只读层被称为镜像,一个镜像是永久不会变的。
由于 Docker 使用一个统一文件系统,Docker 进程认为整个文件系统是以读写方式挂载的。 但是所有的变更都发生顶层的可写层,而下层的原始的只读镜像文件并未变化。由于镜像不 可写,所以镜像是无状态的。
父镜像
每一个镜像都可能依赖于由一个或多个下层的组成的另一个镜像。我们有时说,下层那个 镜像是上层镜像的父镜像。
基础镜像
一个没有任何父镜像的镜像,谓之基础镜像。
镜像ID
所有镜像都是通过一个 64 位十六进制字符串 (内部是一个 256 bit 的值)来标识的。 为简化使用,前 12 个字符可以组成一个短ID,可以在命令行中使用。短ID还是有一定的 碰撞机率,所以服务器总是返回长ID。
获取镜像
1 | docker pull |
国内要配置镜像加速
列出本地镜像
1 | docker images |
在列出信息中,可以看到几个字段信息
- 来自于哪个仓库,比如 ubuntu
TAG
信息,镜像的标记,比如 14.04,区分发行版本- 它的
ID
号(唯一) - 创建时间
- 镜像大小
如果不指定具体的标记,则默认使用 latest
标记信息。
创建镜像
创建镜像有很多方法,用户可以从 Docker Hub 获取已有镜像并更新,也可以利用本地文件系统创建一个。
修改已有镜像
先使用下载的镜像启动容器。
1 | $ sudo docker run -t -i training/sinatra /bin/bash |
注意:记住容器的 ID,稍后还会用到。
在容器中添加 json 和 gem 两个应用。
1 | root@0b2616b0e5a8:/# gem install json |
当结束后,我们使用 exit 来退出,现在我们的容器已经被我们改变了,使用 docker commit
命令来提交更新后的副本。
1 | $ sudo docker commit -m "Added json gem" -a "Docker Newbee" 0b2616b0e5a8 ouruser/sinatra:v2 |
其中,-m
来指定提交的说明信息,跟我们使用的版本控制工具一样;-a
可以指定更新的用户信息;之后是用来创建镜像的容器的 ID;最后指定目标镜像的仓库名和 tag 信息。创建成功后会返回这个镜像的 ID 信息。
使用 docker images
来查看新创建的镜像。
1 | $ sudo docker images |
之后,可以使用新的镜像来启动容器
1 | $ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash |
利用 Dockerfile 来创建镜像
使用 docker commit
来扩展一个镜像比较简单,但是不方便在一个团队中分享。我们可以使用 docker build
来创建一个新的镜像。为此,首先需要创建一个 Dockerfile,包含一些如何创建镜像的指令。
新建一个目录和一个 Dockerfile
1 | $ mkdir sinatra |
Dockerfile 中每一条指令都创建镜像的一层,例如:
1 | # This is a comment |
Dockerfile 基本的语法是
- 使用
#
来注释 FROM
指令告诉 Docker 使用哪个镜像作为基础- 接着是维护者的信息
RUN
开头的指令会在创建中运行,比如安装一个软件包,在这里使用 apt-get 来安装了一些软件
编写完成 Dockerfile 后可以使用 docker build
来生成镜像。
1 | $ sudo docker build -t="ouruser/sinatra:v2" . |
其中 -t
标记来添加 tag,指定新的镜像的用户信息。 “.” 是 Dockerfile 所在的路径(当前目录),也可以替换为一个具体的 Dockerfile 的路径。
可以看到 build 进程在执行操作。它要做的第一件事情就是上传这个 Dockerfile 内容,因为所有的操作都要依据 Dockerfile 来进行。 然后,Dockfile 中的指令被一条一条的执行。每一步都创建了一个新的容器,在容器中执行指令并提交修改(就跟之前介绍过的 docker commit
一样)。当所有的指令都执行完毕之后,返回了最终的镜像 id。所有的中间步骤所产生的容器都被删除和清理了。
*注意一个镜像不能超过 127 层
此外,还可以利用 ADD
命令复制本地文件到镜像;用 EXPOSE
命令来向外部开放端口;用 CMD
命令来描述容器启动后运行的程序等。例如
1 | # put my local web site in myApp folder to /var/www |
现在可以利用新创建的镜像来启动一个容器。
1 | $ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash |
还可以用 docker tag
命令来修改镜像的标签。
1 | $ sudo docker tag 5db5f8471261 ouruser/sinatra:devel |
从本地文件系统导入
要从本地文件系统导入一个镜像,可以使用 openvz(容器虚拟化的先锋技术)的模板来创建: openvz 的模板下载地址为 templates 。
比如,先下载了一个 ubuntu-14.04 的镜像,之后使用以下命令导入:
1 | sudo cat ubuntu-14.04-x86_64-minimal.tar.gz |docker import - ubuntu:14.04 |
然后查看新导入的镜像。
1 | docker images |
上传镜像
用户可以通过 docker push
命令,把自己创建的镜像上传到仓库中来共享。例如,用户在 Docker Hub 上完成注册后,可以推送自己的镜像到仓库中。
1 | $ sudo docker push ouruser/sinatra |
存出和载入镜像
存出镜像
如果要导出镜像到本地文件,可以使用 docker save
命令。
1 | $ sudo docker images |
载入镜像
可以使用 docker load
从导出的本地文件中再导入到本地镜像库,例如
1 | $ sudo docker load --input ubuntu_14.04.tar |
或
1 | $ sudo docker load < ubuntu_14.04.tar |
这将导入镜像以及其相关的元数据信息(包括标签等)。
移除本地镜像
如果要移除本地的镜像,可以使用 docker rmi
命令。注意 docker rm
命令是移除容器。
1 | $ sudo docker rmi training/sinatra |
- 注意:在删除镜像之前要先用
docker rm
删掉依赖于这个镜像的所有容器。
镜像的实现原理
Docker 镜像是怎么实现增量的修改和维护的? 每个镜像都由很多层次构成,Docker 使用 Union FS 将这些不同的层结合到一个镜像中去。
通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD 正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。 Docker 在 AUFS 上构建的容器也是利用了类似的原理。
Docker容器
启动容器
启动容器有两种方式,一种是基于镜像新建一个容器并启动,另外一个是将在终止状态(stopped)的容器重新启动。
因为 Docker 的容器实在太轻量级了,很多时候用户都是随时删除和新创建容器。
新建并启动
所需要的命令主要为 docker run
。
例如,下面的命令输出一个 “Hello World”,之后终止容器。
1 | $ sudo docker run ubuntu:14.04 /bin/echo 'Hello world' |
这跟在本地直接执行 /bin/echo 'hello world'
几乎感觉不出任何区别。
下面的命令则启动一个 bash 终端,允许用户进行交互。
1 | $ sudo docker run -t -i ubuntu:14.04 /bin/bash |
其中,-t
选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i
则让容器的标准输入保持打开。
在交互模式下,用户可以通过所创建的终端来输入命令,例如
1 | root@af8bae53bdd3:/# pwd |
当利用 docker run
来创建容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
启动已终止容器
可以利用 docker start
命令,直接将一个已经终止的容器启动运行。
容器的核心为所执行的应用程序,所需要的资源都是应用程序运行所必需的。除此之外,并没有其它的资源。可以在伪终端中利用 ps
或 top
来查看进程信息。
1 | root@ba267838cc1b:/# ps |
可见,容器中仅运行了指定的 bash 应用。这种特点使得 Docker 对资源的利用率极高,是货真价实的轻量级虚拟化。
守护态运行
更多的时候,需要让 Docker 容器在后台以守护态(Daemonized)形式运行。此时,可以通过添加 -d
参数来实现。
例如下面的命令会在后台运行容器。
1 | $ sudo docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done" |
容器启动后会返回一个唯一的 id,也可以通过 docker ps
命令来查看容器信息。
1 | $ sudo docker ps |
要获取容器的输出信息,可以通过 docker logs
命令。
1 | $ sudo docker logs insane_babbage |
终止容器
可以使用 docker stop
来终止一个运行中的容器。
此外,当Docker容器中指定的应用终结时,容器也自动终止。 例如对于上一章节中只启动了一个终端的容器,用户通过 exit
命令或 Ctrl+d
来退出终端时,所创建的容器立刻终止。
终止状态的容器可以用 docker ps -a
命令看到。例如
1 | sudo docker ps -a |
处于终止状态的容器,可以通过 docker start
命令来重新启动。
此外,docker restart
命令会将一个运行态的容器终止,然后再重新启动它。
进入容器
在使用 -d
参数时,容器启动后会进入后台。 某些时候需要进入容器进行操作,有很多种方法,包括使用docker attach
命令或 nsenter
工具等。
attach 命令
docker attach
是Docker自带的命令。下面示例如何使用该命令。
1 | $ sudo docker run -idt ubuntu |
但是使用 attach
命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候,所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。
nsenter 命令
安装
nsenter
工具在 util-linux 包2.23版本后包含。 如果系统中 util-linux 包没有该命令,可以按照下面的方法从源码安装。
1 | cd /tmp; curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; cd util-linux-2.24; |
使用
nsenter
可以访问另一个进程的名字空间。nsenter 要正常工作需要有 root 权限。 很不幸,Ubuntu 14.04 仍然使用的是 util-linux 2.20。安装最新版本的 util-linux(2.24)版,请按照以下步骤:
1 | $ wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz; tar xzvf util-linux-2.24.tar.gz |
为了连接到容器,你还需要找到容器的第一个进程的 PID,可以通过下面的命令获取。
1 | PID=$(docker inspect --format "{{ .State.Pid }}" <container>) |
通过这个 PID,就可以连接到这个容器:
1 | $ nsenter --target $PID --mount --uts --ipc --net --pid |
下面给出一个完整的例子。
1 | $ sudo docker run -idt ubuntu |
更简单的,建议大家下载 .bashrc_docker,并将内容放到 .bashrc 中。
1 | $ wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker; |
这个文件中定义了很多方便使用 Docker 的命令,例如 docker-pid
可以获取某个容器的 PID;而 docker-enter
可以进入容器或直接在容器内执行命令。
1 | $ echo $(docker-pid <container>) |
导出和导入容器
导出容器
如果要导出本地某个容器,可以使用 docker export
命令。
1 | $ sudo docker ps -a |
这样将导出容器快照到本地文件。
导入容器快照
可以使用 docker import
从容器快照文件中再导入为镜像,例如
1 | $ cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0 |
此外,也可以通过指定 URL 或者某个目录来导入,例如
1 | $sudo docker import http://example.com/exampleimage.tgz example/imagerepo |
*注:用户既可以使用 docker load
来导入镜像存储文件到本地镜像库,也可以使用 docker import
来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。
删除容器
可以使用 docker rm
来删除一个处于终止状态的容器。 例如
1 | $sudo docker rm trusting_newton |
如果要删除一个运行中的容器,可以添加 -f
参数。Docker 会发送 SIGKILL
信号给容器。
数据卷
数据卷volumes
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新,不会影响镜像
- 卷会一直存在,直到没有容器使用
*数据卷的使用,类似于 Linux 下对目录或文件进行 mount。
创建一个数据卷
在用 docker run
命令的时候,使用 -v
标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。
下面创建一个 web 容器,并加载一个数据卷到容器的 /webapp
目录。
1 | $ sudo docker run -d -P --name web -v /webapp training/webapp python app.py |
*注意:也可以在 Dockerfile 中使用 VOLUME
来添加一个或者多个新的卷到由该镜像创建的任意容器。
挂载一个主机目录作为数据卷
使用 -v
标记也可以指定挂载一个本地主机的目录到容器中去。
1 | $ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py |
上面的命令加载主机的 /src/webapp
目录到容器的 /opt/webapp
目录。这个功能在进行测试的时候十分方便,比如用户可以放置一些程序到本地目录中,来查看容器是否正常工作。本地目录的路径必须是绝对路径,如果目录不存在 Docker 会自动为你创建它。
*注意:Dockerfile 中不支持这种用法,这是因为 Dockerfile 是为了移植和分享用的。然而,不同操作系统的路径格式不一样,所以目前还不能支持。
Docker 挂载数据卷的默认权限是读写,用户也可以通过 :ro
指定为只读。
1 | $ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp:ro |
加了 :ro
之后,就挂载为只读了。
挂载一个本地主机文件作为数据卷
-v
标记也可以从主机挂载单个文件到容器中
1 | $ sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash |
这样就可以记录在容器输入过的命令了。
*注意:如果直接挂载一个文件,很多文件编辑工具,包括 vi
或者 sed --in-place
,可能会造成文件 inode 的改变,从 Docker 1.1 .0起,这会导致报错误信息。所以最简单的办法就直接挂载文件的父目录。
数据卷容器
如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。
数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。
首先,创建一个命名的数据卷容器 dbdata:
1 | $ sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres |
然后,在其他容器中使用 --volumes-from
来挂载 dbdata 容器中的数据卷。
1 | $ sudo docker run -d --volumes-from dbdata --name db1 training/postgres |
还可以使用多个 --volumes-from
参数来从多个容器挂载多个数据卷。 也可以从其他已经挂载了数据卷的容器来挂载数据卷。
1 | $ sudo docker run -d --name db3 --volumes-from db1 training/postgres |
*注意:使用 --volumes-from
参数所挂载数据卷的容器自己并不需要保持在运行状态。
如果删除了挂载的容器(包括 dbdata、db1 和 db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时使用 docker rm -v
命令来指定同时删除关联的容器。 这可以让用户在容器之间升级和移动数据卷。具体的操作将在下一节中进行讲解。
利用数据卷容器来备份、恢复、迁移数据卷
可以利用数据卷对其中的数据进行进行备份、恢复和迁移。
备份
首先使用 --volumes-from
标记来创建一个加载 dbdata 容器卷的容器,并从本地主机挂载当前到容器的 /backup 目录。命令如下:
1 | $ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata |
容器启动后,使用了 tar
命令来将 dbdata 卷备份为本地的 /backup/backup.tar
。
恢复
如果要恢复数据到一个容器,首先创建一个带有数据卷的容器 dbdata2。
1 | $ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash |
然后创建另一个容器,挂载 dbdata2 的容器,并使用 untar
解压备份文件到挂载的容器卷中。
1 | $ sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf |
安装docker
环境准备
需要一点点的liunx基础
centos7
使用xshell连接远程服务器进行操作
卸载旧版本
yum remove docker
- 需要的安装包
yum install -y yum-utils
- 设置镜像的仓库
yum-config-manager –add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新索引
yum makecache fast
- 安装docker社区版
yum install docker-ce docker-ce-cli containerd.io
//其他方式
yum clean all yum makecache fastyum -y install docker-ce
- 启动docker
systemctl start docker
- 测试
docker version
docker run hello-world
- 查看镜像在不在
docker images
- 卸载docker
yum remove docker-ce docker-ce-cli containerd.io
yum rm -rf /var/lib/docker
阿里云镜像加速
登录阿里云 找到容器服务
找到镜像加速地址
配置使用
Docker的常用命令
帮助命令
1 | docker version # 显示cker版本信息 |
镜像命令
docker images
1 | [root@localhost ~]# docker images |
docker search 搜索镜像
1 | 可选项目 |
docker pull 下载镜像
1 | [root@localhost ~]# docker pull mysql |
docker rmi 删除镜像 $(docker images -aq) 全部删除
1 | docker rmi -f 镜像 ID #删除指定内容 |
容器命令
1 | docker run [可选参数] image |
启动和停止 容器的操作
1 | docker start 容器id |
常用其他命令
后台启动
1 | # 命令docker run -d 镜像名 |
查看日志命令
1 | docker logs -tf --tail number 容器 |
查看容器中的进程信息
1 | docker top 容器id |
查看镜像的元数据
1 | docker inspect 容器id |
进入当前正在运行的容器
1 | 通常容器都是使用后台 |
方式一 进入之后开启一个新的终端
方式二 进入容器正在执行的终端
从容器内拷贝文件到主机上
1 | docker cp 容器id:容器内路径 目的主机路径 |
以后要部署项目 如果每次进入容器 十分麻烦 webapps 在外部放置项目 就自动同步到内部
1 | #es 暴露的端口很多 |
docker stats 查看cpu的状态
1 | 增加内存限制 修改配置参数 -e 环境配置参数 |
相关自启设置
1 | # linux自动启动docker |
Manjaro基于archlinux的系统 自用备份 可无视
Manjaro安装Docker(自用备份)
基本安装#
1 | Copy# Pacman 安装 Docker |
干掉讨厌的 sudo#
1 | Copy# 如果还没有 docker group 就添加一个 |
Docker 安装mqsql
1 | docker run --privileged=true |
- -p: 将容器的3306的端口映射到主机的3306
- -v
1 |
|
1 | docker run --privileged=true -p 3306:3306 -m 1g --name mysql -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/logs:/var/log/mysql -v /data/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root123 -d mysql:8.0.30 |
开启远程连接权限
1 | 使用Docker命令进去mysql中 |
资料参考: http://www.dockerinfo.net/document ;狂神说java