docker入门小结(一)
入职需要学习docker,记录学习随笔。争取两天大致看完docker学习。博客也算是迁移到cnblogs。
学习的链接参考《docker从入门到实践》http://dockerpool.com/static/books/docker_practice/index.html
源码参考https://github.com/tingfengainiaini/docker_practice,已经fork到我自己的github
另外参考许小圣博客http://www.cnblogs.com/openxxs/p/4634855.html
1,为何要用docker
Docker 是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。
2,安装
Ubuntu 14.04 版本系统中已经自带了 Docker 包,可以直接安装。
$ wget -qO- https://get.docker.com/ | sh
测试docker的状态
$ service docker status
启动docker,并测试一个hello-world
$ service docker start
$ sudo docker run hello-world
3,三个概念
docker的生命周期中有三个概念
- 镜像(Image)
- 容器(Container)
- 仓库(Repository)
一个镜像中可以包含一个系统,系统内可以具体定制需求,镜像便于迁移。容器是从镜像中创建的。容器是从镜像创建的运行实例。它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。仓库是存放镜像的场所。注意注册仓库服务器与仓库的区别。
*注:镜像是只读的,容器在启动的时候创建一层可写层作为最上层。
4,Images镜像
$ sudo docker pull ubuntu:12.04
这样默认从docker hub上获取一个12.04版本的ubuntu,网址是registry.hub.docker.com
$ sudo docker run -t -i ubuntu:12.04 /bin/bash
在刚刚下载的ubuntu12.04中运行bash。查看目录发现是好简洁的阉割版,总共只有134M。
-t
选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i
则让容器的标准输入保持打开。 后面学习创建镜像、修改镜像的方法。
当利用 docker run
来创建容器时,Docker 在后台运行的标准操作包括:
- 检查本地是否存在指定的镜像,不存在就从公有仓库下载
- 利用镜像创建并启动一个容器
- 分配一个文件系统,并在只读的镜像层外面挂载一层可读写层
- 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去
- 从地址池配置一个 ip 地址给容器
- 执行用户指定的应用程序
- 执行完毕后容器被终止
5,镜像管理
存出镜像 $ sudo docker save -o ubuntu_14.04.tar ubuntu:14.04
从本地导入$ sudo cat ubuntu***.tar.gz |docker import - ubuntu:14.042
上传镜像 sudo docker push wx/tingfengaini 这里需要注意push的镜像名字必须格式为<user>/imagename.
把自己创建的镜像上传到仓库中来共享。例如,用户在 Docker Hub 上完成注册后,可以推送自己的镜像到仓库中。
$ docker rm 移除容器;docker rmi 移除镜像。在移除镜像前先要移除依赖于该镜像的所有容器,或者-force删除
$ sudo docker ps -a . 查看正在运行的容器;-a 将列出所有运行过的容器信息;-l 参数列出最近一次运行的容器信息。
例如,下面的命令输出一个 “Hello World”,之后终止容器。
$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world'
Hello world
6,Dockerfile
常用命令:
FROM <image>:<tag> Dockerfile第一条命令
MAINTAINER <name>
RUN <cmd> 等价于 /bin/sh -c;RUN ["executable", "param1", "param2"] 等价于exec
CMD 容器启动时执行,只能有一条有效,如上文的Dockerfile中仅 CMD ["/bin/ls", "-a"]有效 而 CMD /bin/bash 无效
EXPOSE <port> 容器暴露给外界的端口号
ENV <key> <value> 指定环境变量
ADD <src> <dest> 将本地目录(相对Dockerfile所在目录的相对路径)或网络目录或tar文件复制到容器的指定目录中;COPY与之类似,但只能复制本地目录
ENTRYPOINT 容器启动后执行,只能有一条有效
VOLUME ["/data"] 创建可以从本地主机或其他容器挂载的挂载点
USER daemon 指定运行容器时的用户名或UID
WORKDIR workdir 指定后续命名的工作目录
ONBUILD [上面列出的指令均可] 该镜像作为其它新创建镜像的基础镜像时,所执行的指令,即相当于FROM之后再执行ONBUILD指定的指令
测试命令如下:
$ sudo docker build -t="wx/tingfengaini" .
测试该镜像,在usr中找到a。可以用vi查看,发现内容同源文件相同。
7,镜像实现原理(没看懂)
Docker 镜像是怎么实现增量的修改和维护的? 每个镜像都由很多层次构成,Docker 使用 Union FS 将这些不同的层结合到一个镜像中去。
通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk 挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD 正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。 Docker 在 AUFS 上构建的容器也是利用了类似的原理。
这一段话没怎么看懂,大概的意思应该是多层文件使用union FS结合,一个目录下挂载多个disk。
8,容器
8.1 启动
使用镜像启动一个容器(核心就是应用程序):
$ sudo docker run ubuntu:14.04 /bin/echo 'Hello world' Hello world
$ sudo docker run -t -i ubuntu:14.04 /bin/bash root@af8bae53bdd3:/#
其中,-t
选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上, -i
则让容器的标准输入保持打开。
用ps命令查看应用程序运行情况发现仅仅运行了bash以及用来查询的ps命令,节约资源。----货真价实的轻量级虚拟化。
8.2 守护态运行容器、进入容器、容器终止
让 Docker 容器在后台以守护态(Daemonized)形式运行可以通过添加 -d
参数来实现。用docker ps命令查看守护运行的容器。docker ps查看正在运行容器信息。
$ sudo docker run -d wx/tingfengaini /bin/sh -c "while true; do echo hello world; sleep 1; done" 1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147
docker logs id 查看守护容器输出
docker attach 或者nsenter进入容器。具体请看http://dockerpool.com/static/books/docker_practice/container/enter.html
dockerstop id终止容器。docker ps -a查看所有容器信息。docker start / restart重启容器。
8.3 容器导入、导出、删除
docker export导出
docker import导入,注意区别docker load镜像文件导入。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息(即仅保存容器当时的快照状态),而镜像存储文件将保存完整记录,体积也要大。此外,从容器快照文件导入时可以重新指定标签等元数据信息。
docker rm (-f) id 删除
9,仓库
docker login注册仓库
docker search查找仓库
docker pull下载
docker项目可以和GitHub 或 BitBucket自动同步镜像。
这里不再具体的学习,类似github,可以公有仓库也可以私有仓库。
10,数据卷
数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性:
- 数据卷可以在容器之间共享和重用
- 对数据卷的修改会立马生效
- 对数据卷的更新,不会影响镜像
- 卷会一直存在,直到没有容器使用
*数据卷的使用,类似于 Linux 下对目录或文件进行 mount。
sudo docker run -d -P -v /webapp wx/tingfengaini /bin/mkdir /app/a
这里经过尝试发现这种方式加载了一个数据卷到容器的/webapp目录中,并且在该目录中执行mkdir /app/a新建了一个目录,但是容器退出以后,进入该镜像发现并没有该文件夹(这里没搞明白)
如果你有一些持续更新的数据需要在容器之间共享,最好创建数据卷容器。数据卷容器,其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的。
如果删除了挂载的容器(包括 dbdata、db1 和 db2),数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时使用 docker rm -v
命令来指定同时删除关联的容器。 这可以让用户在容器之间升级和移动数据卷。具体的操作将在下一节中进行讲解。
挂在一个本机目录作为数据卷到容器中:
sudo docker run -d -P -v /webapp:/app wx/tingfengaini /bin/mkdir /app/a
sudo docker run -d -P -v /webapp:/app wx/tingfengaini sudo /bin/touch /app/a.txt
在后来才发现docker hub中原来有training/webapp这个镜像文件!之前企图弄一个带python的镜像。