《第一本Docker书》 读书笔记
Posted 山河已无恙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《第一本Docker书》 读书笔记相关的知识,希望对你有一定的参考价值。
写在前面
- 一个之前的项目要去Oracle用teleDB上云。所以需要改好了sql,重新搞一下。拉一个Docker镜像部署一下。
- dokcer没有系统的学习,之前都是应急,同时比较容易上手,所以都是简单学习。
- 博文主要是《第一本Docker书》的一些读书笔记,基本是书里的东西,后期如果有需要会
在我看来,春天里一棵小草生长,它没有什么目的。风起时一匹公马发情,它也没有什么目的。草长马发情,绝非表演给什么人看的,这就是存在本身。我要抱着草长马发情的伟大真诚去做一切事,而不是在人前差羞答答的表演。在我看来,人都是为了要表演,失去了自己的存在。——王小波《三十而立》
第1章 简介
容器
与管理程序虚拟化(hypervisorvirtualization, HV)
有所不同.
管理程序虚拟化
即常说的虚拟机:通过中间层
将一台或多台独立的机器虚拟运行于物理硬件之上
.容器
则是直接运行在操作系统内核之上
的用户空间
。因此,容器虚拟化也被称为“操作系统级虚拟化
”,容器技术可以让多个独立的用户空间
运行在同一台宿主机
上。由于“客居
”于操作系统,容器只能运行与底层宿主机相同或相似的操作系统
。这看起来并不是非常灵活。例如,可以在Ubuntu服务器中运行RedHat Enterprise Linux
,但却无法在Ubuntu服务器上运行Microsoft Windows.
相对于彻底隔离的管理程序虚拟化
,容器
被认为是不安全的。而反对这一观点的人则认为,由于虚拟机
所虚拟的是一个完整的操作系统,这无疑增大了攻击范围,而且还要考虑管理程序层潜在的暴露风险。尽管有诸多局限性,容器还是被广泛部署于各种各样的应用场合。在超大规模的多租户服务部署、轻量级沙盒以及对安全要求不太高的隔离环境中,容器技术非常流行。
- 最常见的一个例子就是“
权限隔离监牢
" (chroot jail),它创建一个隔离的目录环境来运行进程。如果权限隔离监牢中正在运行的进程被入侵者攻破,入侵者便会发现自己“身陷图围",因为权限不足被困在容器创建的目录中,无法对宿主机进行进一步的破坏
。
最新的容器技术引入了OpenVZ, Solaris Zones
以及Linux容器(如lxc)
。使用这些新技术,容器不再仅仅是一个单纯的运行环境。在自己的权限范围内,容器更像是一个完整的宿主机。对Docker
来说,它得益于现代Linux内核特性,如控件组(control group)、命名空间(namespace)技术
,容器和宿主机之间的隔离
更加彻底,容器有独立的网络和存储栈,还拥有自己的资源管理能力
,使得同一台宿主机中的多个容器可以友好地共存。
1.1 Docker简介
Docker
是一个能够把开发的应用程序自动部署
到容器
的开源引擎
。由Docker
公司. (www.docke.com,前dotCloud公司, Paas市场中的老牌提供商)的团队编写,基于Apache .2.0开源授权协议发行。
1.1.1 提供一个简单、轻量的建模方式
Docker
依赖于“写时复制" (copy-on-write)
模型,Docker容器拥有很高的性能,同时同一台宿主机中也可以运行更多的容器,使用户可以尽可能充分地利用系统资源。
1.1.2 职责的逻辑分离
使用Docker
,开发人员
只需要关心容器运行的应用程序
,而运维人员
只需心如何管理容器
。Docker 设计的目的 ,就是要 加强开发人员写代码的开发环境与应用程序要部署的生产环境的一致性,从而降低那种“开发时一切都正常,肯定是运维的问题”的风险。
1.1.3 快速、高效的开发生命周期
Docker的目标之一就是开发、到署、测试到部、上线运行的周期,让你的应用程序具备可移植性,易于构建,并易于协作
。
1.1.4 鼓励使用面向服务的架构
- Docker还鼓励面向服务的架构和微服务架构。.
- Docker推荐单个容器只运行一个应程序或进程,这样就形成了一个
分布式的应用程序模型
,在这种模型下,应用程序或服务都可以表示为一系列内部互联的容器
,从而使分布式部署应用程序,扩展或调试应用程序都变得-非常简单
,同时也提高了程序的内省性
。
1.2 Docker组件
- Docker客户端和服务器,也成为Docker引擎;
- Docker镜像;
- Registry;
- Docker容器。
1.2.1 Docker客户端和服务器
Docker是一个客户端/服务器(C/S)架构的程序。
Docker客户端只需向Docker服务器"或守护进程发出请求,服务器或守护进程将完成所有工作并返回结果。
Docker守护进程有时也称为Docker引擎。
Docker提供了一个命令行工具docker以及一整套RESTful API来与守护进程交互
1.2.2 Docker镜像
镜像是构建Docker世界的基石。用户基于镜像来运行自己的容器。
镜像也是Docker
生命周期的 "构建"部分。镜像是基于联合(Union)文件系统一种层式的结构,)由一系列指令一步一步构建出来。例如:+ 添加一个文件;
- 执行一个命令:
- 打开一个端口。
也可以把镜像当作 容器的“源代码”。镜像体积很小,非常“便携”,易于分享、存储和
1.2.3 Registry
Docker
用Registry来保存用户构建的镜像。Begisty共和私有两种。
Docker
公司运营的公共Registry 叫作Docker Hub。
1.2.4 容器
Docker
可以帮用户构建和部署容器,用户只需要把自己的应用程序或服务打包放进容器即可。
容器是基于镜像启动起来的,容器中可以运一个进程。我们可以认为,镜像是Docker
生命周期中的构建或打包阶段,而 容器则是启动或执行阶段。总结起来, Docker
容器就是:
- 一个镜像格式;·
- 一系列标准的操作;
- 一个执行环境。
Dokeer借鉴了 **标准集装箱**的概念。标准集装箱将货物运往世界各地, Docker
将这个模型运用到自己的设计哲学中,唯一不同的是:集装箱运输货物,而Docker
运输软件。每个容器都包含一个软件镜像,也就是容器的“货物",而且与真正的货物一样,容器里的软件镜像可以进行一些操作,,镜像可以被创建启动、关比。。
像标准集装箱一样, Docker
容器方便替换,可以叠加,易于分发,并且尽量通用。使用Docker
,可以快速构建一个应用程序服务器、一个消息总线、一套实用工具、持续集成( continuous integration, CI)测试环境或者任意一种应用程序、服务或工其。以在本地构建一个完整的测试环境,也可以为生产或开发快速复制一套复杂的应用程序可以说。
1.3 能用Docker
做什么
- 加速本地开发和构建流程,使其更加高效、更加轻量化。本地开发人员可以构建、运行并分享
Docker
容器。容器可以在开发环境中构建,然后轻松地提交到测试环境中,并最终进入生产环境, - 能够让独立服务或应用程序在不同的环境中,得到相同的运行结果。这一点在面向服务的架构和重度依赖微型服务的部署中尤其实用。
- 用
Docker
创建隔离的环境来进行测试。例如,用Jenkins CI这样的持续集成工具启动一个用于测试的容器。 Docker
可以让开发者先在本机上构建一个复杂的程序或架构来进行测试,而不是一开始就在生产环境部署、测试。- 构建一个多用户的平台即服务(Paas)基础设施。
- 为开发、测试提供一个轻量级的独立沙盒环境,或者将独立的沙盒环境用于技术教学,如Unix shell的使用、编程语言教学。
- 提供软件即服务(Saas)应用程序。
- 高性能、超大规模的宿主机部署。
1.4 Docker
与配置管理
Docker
一个显著的特点就是,对不同的宿主机、应用程序和服务,可能会表现出不同的特性与架构(或者确切地说, Docker
本就是被设计成这样的):
Docker
可以是短生命周期的,但也可以用于恒定的环境,可以用一次即销毁,也可以提供持久的服务。这些行为并不会给Docker
增加复杂性,也不会和配置管理工具的需求产生重合。基于这些行为,我们基本不需要担心管理状态的挂状态复杂性,因为容器的生命周期往往比较短,而且重建容器状态的代价通常也比传统的状态修复要低。
1.5 Docker
的技术组件
Docker
可以运行于在何安装了Linux内核的x64主机上。推荐的内核版是3.8或者更高。Docker
的开销比,可以用于服务器、台式机或笔记本。包括以下;
- 一个原生的Linux容器格式,
Docker
中称为1ibcontainer. - Linxu内核的命名空间(namespace) ",用于隔离文件系统、进程和网络。
- 文件系统隔离:每个容器都有自己的root文件系统。
- 进程隔离:每个容器都运行在自己的进程环境中。
- 网络隔离:容器间的虚拟网络接口和IP地址都是分开的。
- 资源隔离和分组:使用cgroups" (即control group, Linux的内核特性之一)将CPU和内存之类的资源独立分配给每个
Docker
容器。 - 写时复制:文件系统都是通过写时复制创建的,这就意味着文件系统是分层的、快速的,而且占用的磁盘空间更小。
- 日志:容器产生的STDOUT, STDERR和STDIN这些io流都会被收集并记入日志,用来进行日志分析和故障排错。交
- 交互式shell:用户可以创建一个伪tty终端,将其连接到STDIN,为容器提供一个交互式的shell.
1.7 Docker
资源
Docker
官方主页(http://www.docker.com/)
Docker Hub (http:/hub.docker.com)
Docker官方博客(http://blog.docker.com/)
Docker官方文档(http://docs.docker.com/)。
Docker快速入门指南(http://www.docker.com/tryit/)
Docker的GitHub源代码(https://github.com/docker/docker)"
Docker Forge (https://github.com/dockerforge): 收集了各种Docker工具、组件和服务。
Docker邮件列表(https://groups.google.com/forum/#!forum/docker-user)
Docker的IRC频道(irc.freenode.net)
Docker的Twitter主页(http://twitter.com/docker)
Docker的StackOverflow问答主页(http://stackoverflow.com/search?q-docker).
Docker官网(http://www.docker.com/)
第2章 安装Docker
Docker
用户界面
Shipyard
: Shipyard提供了通过管理界面来管理各种Docker
资源(包括容器、镜像、宿主机等)的功能。Shipyard是开源的,源代码可以在https://github.com/ehazlett/shipyard获得pockerUl:
DpckerUI
是一个可以与Docker Remote API交互的Web界面。DockerUI是基于AngulaJS框架,采用javascript编写的。
Kitematic: Kitematic是一个OS X和Windows下的GUI界面工具,用于帮助我们在本地运行Docker
以及与Docker Hub进行交互。它是由Docker公司免费发布的产品,也被包含在Docker Toolbox之中。
第3章Docker
入门
3.1确保Docker
已经就绪
[root@liruilong ~]# docker info
Containers: 4
Running: 2
Paused: 0
Stopped: 2
Images: 3
Server Version: 1.13.1
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: journald
Cgroup Driver: systemd
Plugins:
Volume: local
Network: bridge host macvlan null overlay
Swarm: inactive
Runtimes: docker-runc runc
Default Runtime: docker-runc
Init Binary: /usr/libexec/docker/docker-init-current
containerd version: (expected: aa8187dbd3b7ad67d8e5e3a15115d3eef43a7ed1)
3.2运行我们的第一个容器
[root@liruilong ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/rabbitmq management 485c275e2364 5 weeks ago 252 MB
docker.io/nginx latest 35c43ace9216 5 months ago 133 MB
docker.io/mamohr/centos-java latest e041132b8b32 3 years ago 577 MB
[root@liruilong ~]# docker run -i -t e041132b8b32 /bin/bash
[root@899c72cacb59 /]# ls
anaconda-post.log bin dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
[root@899c72cacb59 /]# uname
Linux
[root@899c72cacb59 /]#
-i
标志保证容器中STDIN是开启的,尽管我们并没有附着到容器中。持久的标准输入是交互式shell的半边天。-t
标志则是另外,它docker为要创建的容器分配·一个伪tty终端。这样,新创建的容器才能提供一个交互式shell.若要在命令行下创建一个,我们能与之进行交互的容器,而不是一个运行后台服务的容器,则这两个参数已经是最基本的参数了。
Docker会检查本地是否是存在镜像,如果本地还没有该镜像的话,那么Docker就会连接官方维护的DotrHub Rggistry,查看Docker Hub中是否有该镜像
。Docker一旦找到该镜像,就下载镜像并将共保存到本地宿主机中。
Docker在文件系统内部用这个镜像创全新容器。该容器拥有自己的网络IP地址/以及一个用来和宿主机进行通信 桥接网络接口。最后,我们告诉Docker在新容器中要运行什么命令,在本例中我们在容器行/bin/bash命令启动了一个Bash shell.
3.3使用第一个容器
[root@liruilong ~]# docker run -i -t e041132b8b32 /bin/bash
[root@e98c71f36f2d /]# hostname
e98c71f36f2d
[root@e98c71f36f2d /]# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.5 e98c71f36f2d
[root@e98c71f36f2d /]# yum provides ifconfig
Loaded plugins: fastestmirror, ovl
base | 3.6 kB 00:00:00
extras | 2.9 kB 00:00:00
updates | 2.9 kB 00:00:00
。。。。。。
net-tools-2.0-0.25.20131004git.el7.x86_64 : Basic networking tools
Repo : base
Matched from:
Filename : /sbin/ifconfig
[root@e98c71f36f2d /]# yum -y install net-tools-2.0-0.25.20131004git.el7.x86_64
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
。。。。
[root@e98c71f36f2d /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.18.0.5 netmask 255.255.0.0 broadcast 0.0.0.0
inet6 fe80::42:acff:fe12:5 prefixlen 64 scopeid 0x20<link>
ether 02:42:ac:12:00:05 txqueuelen 0 (Ethernet)
RX packets 2797 bytes 30739967 (29.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2625 bytes 176315 (172.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@e98c71f36f2d /]# yum update && yum -y install vim
用户可以继续在容器中做任何自己想做的事情。当所有工作都结束时,输入exit
),容器现在以经停止运行了!
在指定的/bin/bash
命令处于运行状态的时候,我们的容器也才会地处于运行状态。一旦退出容器, /bin/bash命令也就结束了,这时容器随之停止了运行。但容器仍然是存在的,可以docker ps-a
命查看当前系统中容器的列表,
有3种方式可以唯一指代容器:
- 短DUD(如f7cbdac22a02)、
- 长UUID(7cbdac02er3c9438c729345e54db9d20cfa2ac1fc3494b6eb60872e74778)
- 名称(如gray-cat)。
3.4容器命名
$ sudo docker --name boy_the_container -i-t ubuntu /bin/bash
定器的命名必须是唯一的。如果试图创建两个名称相同的容器》则命令将会失败。如果要使用的容器名称已经存在,可以先用dockerrmf删除已有的同名容器后,再来创建新的容器。
3.5重新启动已经停止的容器
sudo docker start bpb the container
也可以使用docker restart
命令来重新启动一个容器。这时运行不带-a
标志的docker ps
命令,就应该看到我们的容器已经开始运行了。注意类似地, Docker也提供(docker create
命令来创建一个容器,但是并不运行它。这让我们可以在自己的容器工作流中对共进行细杠度的控制。
3.6附着到容器上
sudo docker attach container
3.7创建守护式容器
sudo docker run --name daemon_daved -d ubuntu /bin/sh-c "while true;do echo tettewera;seelp 1; done"
3.8容器内部都在干些什
sudo docker logs -f daemon dave
- 我们也可以跟踪容器日志的某 段,和之前类似,只需要在tail命加入-f—tail标志即可。例如,可以
docker logs --tail 10 daemon_dave
获取日志最后10行内容。另外,也可以docker logs --tail 0 -f daemon_dave
命令来追踪某个容器的最新日志- 还可-t标志为每条日志项加上时间戳
sudo docker logs -ft daemon dave
3.9 Docker日志驱动
自Docker 1.6
开始,也可以控制Docker
守护进程和容器的日志驱动,--1og-driver
选项现。可以在启动Docker守护进程或执行docker run命令
有好几个选项,包括默认json-file
, json-file
也为我 前面看到的docker logs命令提供了基础。
其他的选项还syslog,该选项将禁用docker logs命令,形 将所有容器志输 都重定向Syslog.可以在启动docker守护进程时指定该选项。
sudo docker run --name daemon_daved --log-driver="syslog" -d ubuntu /bin/sh -c "while true; do echo hello word; sleep 1; done"
取还有一个可用的选项是none,这个选项将会禁用所有容器中的日志,导致docker logs
命令也被禁用
3.10查看容器内的进程
查看容器运行的讲程,要做到这一使用docker top
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ sudo docker top daemon_daved
PID USER TIME COMMAND
25931 root 0:00 /bin/sh -c while true; do echo hello word; sleep 1; done
26291 root 0:00 sleep 1
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$
3.11 Docker统计信息
sudo docker stats daemon_daved
3.12在容器内部运行进程
在Docker 1.3之后,也可以通过docker exec
命令在容器内部额外启动新进程。
- 在容器内运行的进程有两种:后台任务和交互式任务。
- 后台任务在容器内且没有交互需求,而交互式在务则保持在前台行。
- 对于需要在容器内 打开shell的在务,互式务很实用的。
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ sudo docker exec -d daemon_daved touch /etc/new_config_file
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ sudo docker exec -ti daemon_daved /bin/bash
root@232b4ca6dd68:/# ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
root@232b4ca6dd68:/#
- 这里的
-t
和-i
标志为我们执行的进程创TTY并捕护STDIN,接着我们指定了要在内部执行这个命令的容器的名字以及要执命。在上面的例子中,这条命令会在daemon-dave
容器内创建一个新的bash会话,有了这个会话,我们就可以在该容器中运行其他命令了。
从Docker 1.7
开始,可以对docker exec
启动的进程使用-u
标志为新启动的进程指定,一个用户属主。
docker exec
命令是Docker 1.3
引入的,早期版本并不支持该命令。对于早期Docker版本,请参考第6章中介绍的nsenter命令。
3.13停止守护式容器
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
232b4ca6dd68 ubuntu "/bin/sh -c 'while t…" 17 minutes ago Up 17 minutes daemon_daved
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ sudo docker stop 232b4ca6dd68
232b4ca6dd68
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$
└─$ docker ps -n 2
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
232b4ca6dd68 ubuntu "/bin/sh -c 'while t…" 18 minutes ago Exited (137) 42 seconds ago daemon_daved
166f786ffb04 9dbed5a04e9c "/bin/sh -c 'yum upd…" 5 hours ago Exited (127) 5 hours ago elegant_roentgen
3.14自动重启容器
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ sudo docker run --restart=always --name daemon_daved -d ubuntu /bin/sh -c "while true; do echo hello word; sleep 1; done"
c030ed0db34903039a104816094887d884bcefff767c2ac056bd8a64d294dce9
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$
--restart
标志被设置为always
,无论容器退出代碼是什麽,Docker都会自动重启该容器,
还可以将这个标志为on-failure
,这样,只有当容器的退出代码为非0值的时候)才会自动重启。
on-failure
还一个可选的重启次数.--restart=on-failure:4
3.15深入容器
通过docker ps
命令获取容器的信息,还可以使用docker inspect
来获得更多的容器信息,也可用-f
或者--format
标志来定查看结果
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ sudo docker inspect --format='{{ .State.Running }}' c030ed0db349
true
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$ sudo docker inspect --format='{{ .NetworkSettings.IPAddress }}' c030ed0db349
172.17.0.2
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/uag/uag_jdk]
└─$
也可以同时指定多个容器,并显示每个容器的输出结果,
3.16删除容器
如果容器已经不再使用,可以docker rm
命令删除它们,
从Docker 1.6.2
开始,可以通过给docker rm
命全传 -f
标志来删除运行中的Docker
sudo docker rm `sudo docker ps--a -q`
-a
标志代表列出所有容器,而-g
标,志则表示只需要返回容器的ID而不会返回容器的其他信息。这样我们就得到了容器ID
的列,表,并传给了docker rm
命令,从而达到删除所有容器的目的。
第4章使用Docker镜像和仓库
4.1什么是Docker镜像
Docker
镜像是由文件系统叠加而成,底端是一个引导文件系统bootfs
。Docker
用户几乎永远不会和引导文件交互。实际上,当一个容器启动.后,它将会被移到内存中,而引导文件系统则会被卸载(unmount),以留出更多的内存供initrd磁盘镜像
使用。
Docker
看起来还很像一个典型的Linux虚拟化栈
。实际, Docker镜像的第二层是root文件系统rootfs
, 位于引导文件系统之上。
rootfs
可以或多种操作系如Debian
或者ubuntu
文件系统)。在传统的Linux引导过程中, root文件系统会最先以只读的方式加载
,当引导结束并完成了完整性检查之后
,它才会被切换为读写模式
是在Docker
里, root文件
系统永远只能是只读状态
,并且Docker
利用联合加载
(union mount)技术又会在root文件系统层
上加载更多的只读文件系统
。
联合加载是指同时加载多个文件系统,但是在外面看起术只能看到只有一个文件系统。联合加载
会将各层文件系统叠加到一起。
Docker
将这样的文件系统
称为镜像
。一个镜像
可以放到另一个镜像
的顶部。位于下面的镜像
称为父镜像(parent image)
,可以依次类推,直到镜像栈的最底部,最底部的镜像称为基础镜像(base image)
,最后,当从一个镜像启动容器时, Docker
会在该镜像的最顶层加载一个读写文件系统
。我们想在Docker中运行的程序就是在这个读写层中执行
的。
当Docker
第一次启动一个容器
时,初始的读写层
是空
的。当文件系统发生变化时,这些变化都会应用到这一层上。比如,如果想修改一个文件
- 这个
文件
首先会从该读写层下面的只读层复制到该读写层
。该文件的只读版本依然存在,但是已经被读写层中的该文件副本所隐藏。通常这种机制被称为写时复制(copy on write)
,这也是使Docker如此强大的技术之一。 - 每个
只读镜像层
都是只读
的,并且以后永远不会变化。当创建一个新容器
时,Docker会构建出一个镜像栈
,并在栈
的最顶端添加一个读写层
。这个读写层再加上其下面的镜像层以及一些配置数据,就构成了一个容器。
4.2列出镜像
本地镜像都保存在Docker宿主机的/var/lib/docker
目录下。每个镜像都保存在Docker
所采用的存储驱动目录下面,如aufs
或者devicemapper
。也可以在/var/lib/docker/containers
目录下面看到所有的容器。
docker images
4.3拉取镜像
docker pull image_name
4.4查找镜像
docker search image_name
4.5构建镜像
使用docker commit
命令。使用docker build
命令和Dockerfile
文件。
docker commit 容器ID 镜像名
-旦有了Dockerfile
,我们就可以使用docker build
命令基于该Dockerfile中的指令构建一个新的镜像。
FROM ubuntu:18.04
LABEL maintainer="james@example.com"
RUN apt-get update
RUN apt-get install -y nginx
RUN echo 'Hi, I am in your container' \\
>/var/www/html/index.html
EXPOSE 80
4.5.1 创建Docker Hub账号
4.5.2 用Docker的commit命令创建镜像
4.5.3 用Dockerfile构建镜像
每条指令都会创建一个新的镜像层并对镜像进行提交
。Docker
大体上按照如下流程执行Dockerfile
中的指令。
- Docker从基础镜像运行一个容器。
- 执行一条指令,对容器做出修改。
- 执行类似docker commit的操作,提交一个新的镜像层。
- Docker再基于刚提交的镜像运行一个新容器。
- 执行Dockerfile中的下一条指令,直到所有指令都执行完毕。
RUN指令会在shell里使用命令包装器/bin/sh -c
来执行。如果是在一个不支持shell的平台上运行或者不希望在shell中运行(比如避免shell字符串篡改),也可以使用exec格式的RUN指令
``bash
RUN [ “apt-get”, " install", “-y”, “nginx”]
从Git仓库构建Docker镜像
```bash
$ sudo docker build-t="jamtur01/static web:v1" \\ git@github.com: jamtur01/docker-static web
4.5.6 Dockerfile和构建缓存
由于每一步的构建过程都会将结果提交为镜像,所以Docker
的构建镜像过程就显得非常聪明。它会将之前的镜像层看作缓存。
有些时候需要确保构建过程不会使用缓存
。要想略过缓存功能,可以使用docker build的--no-cache
标志
4.5.7 基于构建缓存的Dockerfile模板
构建缓存带来的一个好处就是,我们可以实现简单的Dockerfile模板(比如在Dockerfile文件顶部增加包仓库或者更新包,从而尽可能确保缓存命中),我一般都会在自己的Dockerfile文件顶部使用相同的指令集模板,比如对Ubuntu.使用模版。
FROM ubuntu:18.04
LABEL maintainer="james@example.com"
ENV REFRESHED_AT 2016-06-01
RUN apt-get -qq update
分析一下这个新的
Dockerfile
,首先,我通过FROM
指令为新镜像设置了一个基础镜像ubuntu:14.04
。接着,我又使用MAINTAINER
指令添加了自己的详细联系信息。之后我又使用了一条新出现的指令ENV来在镜像中设置环境变量。在这个例子里,我通过ENV
指令来设置了一个名为REFRESHED_AT
的环境变量,这个环境变量用来表明该镜像模板最后的更新时间。最后,我使用了RUN指令来运行apt-get -qq update命令。该指令运行时将会刷新APT包的缓存,用来确保我们能将要安装的每个软件包都更新到最新版本。有了这个模板,如果想刷新一个构建,只需修改ENV指令中的日期。这使Docker在命中ENV指令时开始重置这个缓存,并运行后续指令而无须依赖该缓存
。
4.5.8查看新镜像
4.5.9从新镜像启动容器
4.5.10 Dockerfile指令
4.6将镜像推送到DockerHub
4.7删除镜像
4.8运行自己的DockerRegistry
4.9其他可选Registry服务
第5章在测试中使用Docker
- 使用Docker测试一个静态网站。
- 使用Docker创建并测试一个Web应用。
- 将Docker用于持续集成。
5.1使用Docker测试静态网站(Nginx docker 化)
使用Nginx Web
服务器安装到容器来架构一个简单的网站开始。这个网站暂且命名为Sample.
5.1.1 Sample网站的初始Dockerfile
- 获取Nginx配置文件:
global.conf
server {
listen 0.0.0.0:80;
server_name _;
root /var/www/html/website;
index index.html index.htm;
access_log /var/log/nginx/default_access.log;
error_log /var/log/nginx/default_error.log;
}
nginx.conf
user www-data;
worker_processes 4;
pid /run/nginx.pid;
daemon off;
events { }
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
gzip_disable "msie6";
include /etc/nginx/conf.d/*.conf;
}
我们还需要将Nginx配置为非守护进程的模式,这样可以让Nginx在Docker容器里工作。
网站测试的基本Dockerfile
FROM ubuntu:18.04
LABEL maintainer="james@example.com"
ENV REFRESHED_AT 2014-06-01
RUN apt-get -qq update && apt-get -qq install nginx
RUN mkdir -p /var/www/html/website
ADD nginx/global.conf /etc/nginx/conf.d/
ADD nginx/nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
这个简单的Dockerfile内容包括以下几项。
- 安装Nginx.·
- 在容器中创建一个目录/var/www/html/website/
- 将来自我们下载的本地文件的Nginx配置文件添加到镜像中。
- 公开镜像的80端口。
这个Nginx配置文件是为了运行Sample网站而配置的。将文件nginx/global.conf用ADD指令复制到/etc/nginx/conf.d/目录中。
在nginx.conf这个配置文件里, daemon off;选项阻止Nginx进入后台,强制其在前台运行。这是因为要想保持Docker容器的活跃状态,需要其中运行的进程不能中断。默认情况下, Nginx"会以守护进程的方式启动,这会导致容器只是短暂运行,在守护进程被fork启动后,发起守护进程的原始进程就会退出,这时容器就停止运行了。
5.1.2构建Sample网站和Nginx镜像
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/logstash/sample]
└─$ sudo docker build -t jamtur01/nginx .
Sending build context to Docker daemon 4.608kB
Step 1/8 : FROM ubuntu:18.04
---> 39a8cfeef173
Step 2/8 : LABEL maintainer="james@example.com"
---> Using cache
....
Removing intermediate container 15c4f81371e1
---> 1583c3126a40
Successfully built 1583c3126a40
Successfully tagged jamtur01/nginx:latest
5.1.3从Sample网站和Nainx镜像构建容器
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/sample]
└─$ sudo docker run -d -p 81:80 --name website -v $PWD/website:/var/www/html/website jamtur01/nginx nginx
7bb1eaa70f46e565b940b83fd0129ad9d5b2c035278d7d9c2704187e08f4e43f
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/sample]
可以看到,我们使用docker run命令从jamtur01/nginx镜像创建了一个名为website的容器。读者已经见过了大部分选项,不过-v选项是新的。-v这个选项允许我们将宿主机的目录作为卷,挂载到容器里。现在稍微偏题一下,我们来关注一下卷这个概念。卷在Docker里非常重要,也很有用。卷是在一个或者多个容器内被选定的目录,可以绕过分层的联合文件系统(Union FileSystem),为Docker提供持久数据或者共享数据。这意味着对卷的修改会直接生效,并绕过镜像。当提交或者创建镜像时,卷不被包含在镜像里.
卷可以在容器间共享
。即便容器停止,卷里的内容依旧存在
。
当我们因为某些原因不想把应用或者代码构建到镜像中时,就体现出卷的价值了。例如:希望同时对代码做开发和测试;代码改动很频繁,不想在开发过程中重构镜像;希望在多个容器间共享代码。
sudo docker run -d -p 81:80 --name website -v $PWD/website:/var/www/html/website:ro jamtur01/nginx nginx
-v选项通过指定一个目录或者登上与容器上与该目录分离的本地宿主机来工作,这两个目录用:分隔。如果容器目录不存在,
Docker会自动创建一个。也可以通过在目录后面加上rw或者ro来指定容器内目录的读写状态
5.1.4修改网站
5.2使用Docker构建并测iWeb应用程序
测试一个基于Sinatra的Web应用程序,而不是静态网站,然后我们将基于Docker来对这个应用进行测试。
Sinatra是一个基于Ruby的Web应用框架,它包含一个Web应用库,以及简单的领域专用语言(即DSL)来构建Web应用程序。与其他复杂的Web应用框架(如Ruby on Rails)不同, Sinatra并不遵循MVC模式,而关注于让开发者创建快速、简单的Web应用。
Sinatra非常适合用来创建一个小型的示例应用进行测试。在这个例子里,我们将创建一个应用程序,它接收输入的URL参数,并以JSON散列的结构输出到客户端。通过这个例子,我们也将展示一下如何将Docker容器链接起来。
5.2.1 构建Sinatra应用程序
我们先来创建一个sinatra目录,用来存放应用程序的代码,以及构建时我们所需的文件。
FROM ubuntu:18.04
LABEL maintainer="james@example.com"
ENV REFRESHED_AT 2014-06-01
RUN apt-get update && apt-get -y install ruby ruby-dev build-essential redis-tools
RUN gem install --no-rdoc --no-ri sinatra json redis
RUN mkdir -p /opt/webapp
EXPOSE 4567
CMD [ "/opt/webapp/bin/webapp" ]
5.2.2 创建Sinatra容器
5.2.3 扩展Sinatra应用程序来使用Redis
5.2.4 将Sinatra应用程序连接到Redis容器
5.2.5 Docker内部连网
5.2.6 DockerNetworking
5.2.7 使用容器连接来通信
5.2.8 连接容器小结
# 第6章使用Docker构建服务
6.1 构建第一个应用
使用Jekyll
框架的自定义网站。我们会构建以下两个镜像。
- 一个镜像安装了Jekyll及其他用于构建Jekyll网站的必要的软件包。
- 一个镜像通过Apache来让Jekyll网站工作起来。
我们打算在启动容器时,通过创建一个新的Jekyll网站来实现自服务。工作流程如下。
- 创建Jekyll基础镜像和Apache镜像(只需要构建一次)。
- 从Jekyll镜像创建一个容器,这个容器存放通过卷挂载的网站源代码。
- 从Apache镜像创建一个容器,这个容器利用包含编译后的网站的卷,并为其服务。
在网站需要更新时,清理并重复上面的步骤。
可以把这个例子看作是创建一个多主机站点
最简单的方法。实现很简单,本章后半部分会以这个例子为基础做更多扩展。
6.1.1 Jekyll基础镜像
编写jekyll对应的Dockerfile
文件
FROM ubuntu:18.04
LABEL maintainer="james@example.com"
ENV REFRESHED_AT 2016-06-01
RUN apt-get -qq update
RUN apt-get -qq install ruby ruby-dev libffi-dev build-essential nodejs
RUN gem install --no-rdoc --no-ri jekyll -v 2.5.3
VOLUME /data
VOLUME /var/www/html
WORKDIR /data
ENTRYPOINT [ "jekyll", "build", "--destination=/var/www/html" ]
- 镜像基于Ubuntu 14.04,并且安装了Ruby和用于支持Jekyll的包。然后我们使用VOLUME指令创建了以下两个卷。,/data/,用来存放网站的源代码。./var/www/htm1/,用来存放编译后的Jekyll网站码然后我们需要将工作目录设置到/data/,并通过ENTRYPOINT指令指定自动构建的命令,这个命令会将工作目录/data/中的所有的Jekyll网站代码构建到/var/www/html/目录中。
6.1.2 构建Jekyl基础镜像
PS E:\\docker> bash
┏━(Message from Kali developers)
┃
┃ This is a minimal installation of Kali Linux, you likely
┃ want to install supplementary tools. Learn how:
┃ ⇒ https://www.kali.org/docs/troubleshooting/common-minimum-setup/
┃
┗━(Run: “touch ~/.hushlogin” to hide this message)
┌──(liruilong㉿Liruilong)-[/mnt/e/docker]
└─$ mkdir jekyll
┌──(liruilong㉿Liruilong)-[/mnt/e/docker]
└─$ cd jekyll/;vim Dockerfile
┌──(liruilong㉿Liruilong)-[/mnt/e/docker/jekyll]
└─$ sudo docker build -t jamtur01/jekyll .
[sudo] password for liruilong:
Sending build context to Docker daemon 2.048kB
Step 1/10 : FROM ubuntu:18.04
18.04: Pulling from library/ubuntu
feac53061382: Pull complete
Digest: sha256:7bd7a9ca99f868bf69c4b6212f64f2af8e243f97ba13abb3e641e03a7ceb59e8
Status: Downloaded newer image for ubuntu:18.04
---> 39a8cfeef173
Step 2/10 : LABEL maintainer="james@example.com"
---> Running in d11e8cdaf982
Removing intermediate container d11e8cdaf982
。。。。
6.1.3 Apache镜像
构建 apache Dockerfile文件
RUN apt-get -qq update
RUN apt-get -qq install apache2
VOLUME ["/var/www/html"]
WORKDIR /var/www/html
# 定义环境变量
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE以上是关于《第一本Docker书》 读书笔记的主要内容,如果未能解决你的问题,请参考以下文章