the-docker-book
Table of Contents
- Chapter 1: Introduction
- Chapter 2: Installing Docker
- Chapter 3: Getting Started with Docker
- Ensuring Docker is ready
- Building our first container
- Working with our first container
- Container naming
- Staring a stopped container
- Attaching to a container
- Creating daemonized containers
- Seeing what's happening inside our container
- Inspecting the container's processes
- Stopping a daemonized container
- Finding out more about our container
- Deleting a container
- Chapter 4: Working with Docker images and repositories
Chapter 1: Introduction
- 首先我们要区分两个概念:
- hypervisor virtualiation: 是指在一个物理机器上面,通过中间层,运行多个相互独 立的"虚拟机(machine)". hypervisor 隔绝的是多个machine
- container: 是在user space运行的,不会创建独立的Machine. 所以container又叫做 system-level virtualization. container隔绝的是多个user space instance
- 正是由于两者的差异, container可以说是不如hypervisor"灵活":
- container只可以在ubuntu上面运行RedHat
- hypervisor不仅仅可以在ubuntu上面运行RedHat,还能在ubuntu上面运行windows
- 相比于拥有完整操作系统的hypervisor, docker有优点也有缺点:
- 缺点是可能没那么安全
- 优点是比较节省资源
- docker是新一代的container,旨在让container技术更加的容易使用.
Introducing Docker
- docker相比于其他container,有如下的优点:
- 轻量级: docker非常的轻量而且快速, 因为基于copy-on-write model, 只有需要改 的地方才做了改动
- 有了docker, 开发人员和运维人员的职责分开了: 开发人员专注于开发好container 里面的内容, 运维人员维护管理好container就好了.在docker的帮助下,运维人员可 以"百分百"的确认, 开发人员写的代码,和自己部署的代码是同一套,避免了在dev下 成立,但是运维的时候失败的问题
- Docker的组成部分有如下:
- Docker Client和Docker server
- Docker Images
- Registries
- Docker Containers
Docker client and Server
- Docker整体上来看,是一个CS结构的应用, Docker Client是通过和Docker Server(或者 是daemon)交流来获取能力的.
- 你可以把Client以及Server放在同一个或者不同的机器上面
Docker images
- image是Docker世界的基石.container就是从image开始启动的.
- image是通过一系列指令来创建的, 比如:
- 添加一个文件
- 运行一个命令
- 打开一个端口
- 你可以把image想象成container的"source code", 而且image像git管理的代码一样,可 以方便的进行分享,存储和升级.
Registries
- Docker通过Registry来存储你的image,就像repo存储你的git code一样.
- registry也是区分public和private的, 和git的repo一样
Containers
- container就是启动了的image,里面可能有一个或者多个运行的process
- 对, 如果把image看做是静态代码的话, container就是code的运行时态
- container保存的是process,所以就像process可以created, started, stopped, restarted, destroyed一样, container也可以有这些过程
- 对于docker来说,container的运行方法是完全一样的,就好像对于船坞(docker)来说,集 装箱都是一样的,堆起来就可以
- container里面有什么并不重要, docker会按照自己永远不变的程式运行它,就像船坞对 待集装箱一样,拿一个一样大小的夹子,夹起来,放到卡车上
Docker's technical components
- docker需要x64位的Linux kernel支持(推荐version3.8以后版本)
- docker的一些基本要求如下:
- Linux container format: libcontainer
- Linux kernel namespces: 用来隔绝filesystem, process, network
- Filesystem isolation: 每个container都有自己的root filesystem
- Process isolation: 每个container都有自己的process系统
- Network isolation: 不同的container有不同的virtual interface 和 IP Address
- Resource isolation and grouping: 像CPU和memory这种资源的分配,靠的是cgroups 命令(Linux下面的特性)
- Copy-on-Write: 文件系统是copy-on-write的,也就是所有container用一套基础,有 改动才增加一层.
- Logging: STDOUT, STDERR, STDIN都会被保存然后留以后进行分析
- Interactive shell: 可以创建一个shell连接STDIN
Chapter 2: Installing Docker
Requirements
- Docker的安装需要一些基本的要求:
- 64-bit architecture, 32-bit的不支持
- 需要Linux 3.8 以上版本的内核(某些2.6版本的可能也行)
- The kernel 必须支持一些storage driver:
- Device Mapper (默认支持)
- AUFS
- vfs
- btrfs
Boot2Docker installation on Windows and OSX
- Windows和Mac是没有Linux kernel支持的,所以需要virtualbox的支持, virtualbox其 实内部就是装了一个tinyCoreLinux
- 安装了virtualBox的tinyCoreLinux以后,你要能够连接这个Linux的话,那么就得有个 command line连接这个tinyCoreLinux.这个工具就是The Docker client
Using Boot2Docker with this book
- 如果是Boot2Docker来运行本书的例子的话,有时候你要连接localhost, 本书里面的
localhost并不是127.0.01,而是tinyCoreLinux,所以要知道这个tinyCoreLinux的ip地
址(也就是VirtualBox虚拟机的地址),需要如下命令
c:\code>boot2docker ip boot2docker ip The VM's Host only interface IP address is: 192.168.59.103
- boot2docker是不支持-v这个参数的,因为tinyCoreLinux里面的盘分享给docker instance 是没有意义的.
The Docker daemon
- 安装Docker以后,我们必须确认Docker daemon是否在运行
- Docker的daemon是root-privileged的
- docker 命令行命令其实就是作为这个daemon(server)的client, 也同时需要root权限
- docker daemon是监听如下的一个Unix socket来接受incoming Docker request
> ls -al /var/run/docker.sock srw-rw---- 1 root docker 0 Mar 15 03:49 /var/run/docker.sock
- 从上面的输出我们可以看到:如果一个机器上面有个用户组名字是docker, 那么这个这
个group docker就会被设置成/var/run/docker.sock的owner,也就不用sudo就可以调用
了, 在linux下安装docker不一定会创建docker group的,但是boot2docker默认为我们
创建了docker group
> cat /etc/group root:x:0: lp:x:7:lp nogroup:x:65534: staff:x:50:docker docker:x:100:docker
- 需要极为注意的是docker group虽然用起来方便,但的确是一个太高权限的group,有可 能成为他人利用漏洞, 在向此group加成员的时候,要十分小心
Configuring the Docker daemon
- 默认情况下, docker daemon是绑定了某个端口的(比如2376)
> sudo netstat -ltnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 623/sshd tcp 0 0 :::22 :::* LISTEN 623/sshd tcp 0 0 :::2376 :::* LISTEN 701/docker
- 如果我们想把docker dameon, 换到2375这个端口,那么要使用参数-H, 下面这个例子
就说明docker已经成功启动了.
sudo netstat -ltnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 623/sshd tcp 0 0 :::22 :::* LISTEN 623/sshd tcp 0 0 :::2376 :::* LISTEN 701/docker sudo kill -9 701 sudo netstat -ltnp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 623/sshd tcp 0 0 :::22 :::* LISTEN 623/sshd sudo docker -d -H tcp://0.0.0.0:2375 2015/03/15 13:05:53 docker daemon: 1.3.1 4e9bbfa; execdriver: native; graphdriver: [ccef5f24] +job serveapi(tcp://0.0.0.0:2375) [info] Listening for HTTP on tcp (0.0.0.0:2375) [info] /!\ DON'T BIND ON ANOTHER IP ADDRESS THAN 127.0.0.1 IF YOU DON'T KNOW WHAT YOU'RE DOING /!\ [ccef5f24] +job init_networkdriver() [ccef5f24] -job init_networkdriver() = OK (0) [info] Loading containers: ..[info] : done. [ccef5f24] +job acceptconnections() [ccef5f24] -job acceptconnections() = OK (0)
- 我们甚至可以使用-H来指定不是/var/run/docker.sock的另外的一个unix socket文件
$ sudo /usr/bin/docker -d -H unix://home/docker/docker.sock
- 需要注意的是-d参数的作用是开启"debug模式", 你会在前一个例子中发现大量的[info] 等,就是开启debug模式的结果
Checking that the Docker daemon is running
Ubuntu like
- 可以使用如下命令来查看docker的状态
> sudo status docker [ OK ]
- 可以使用start 和stop来启动docker
> sudo stop docker > sudo start docker
RedHat like
- 可以使用如下命令开启关闭
> sudo service docker stop > sudo service docker start
Chapter 3: Getting Started with Docker
Ensuring Docker is ready
- 首先,我们要确认docker binary存在并且运行良好
> docker info Containers: 2 Images: 18 Storage Driver: aufs Root Dir: /mnt/sda1/var/lib/docker/aufs Dirs: 22 Execution Driver: native-0.2 Kernel Version: 3.16.4-tinycore64 Operating System: Boot2Docker 1.3.1 (TCL 5.4); master : 9a31a68 - Fri Oct 31 03:14:34 UTC 2014 Debug mode (server): true Debug mode (client): false Fds: 11 Goroutines: 11 EventsListeners: 0 Init Path: /usr/local/bin/docker
- docker这个binary在前面的章节是server的作用,在这里已经是client的作用了.就是 发送request去docker daemon,然后得到反馈以后进行处理
Building our first container
- 我们下面使用docker run来创建Docker container(从image变成container),没有image
下载的过程是因为原来下载过ubuntu image.
docker run -i -t ubuntu /bin/bash root@1cdeb856c365:
- 分析一下这个命令:
- docker run是命令主体.是创建container(从image开始)
- -i和-t两个参数的意思是: -i保证STDIN为container开启. -t保证为container提供 一个pseudo-tty,也就是给container一个interactive shell
- 下面ubuntu的意思是我们要使用image ubuntu, 这个image是base image(也就是没 有x/y这种结构,而是只有y).base image是docker inc提供的.我们这里没有网络操作 是因为本地有image, 如果没有image,那么会从网络下载
- /bin/bash, docker得到这个image以后,会在当前file system里面创建一个新的container
然后在这个container的/bin/bash命令,也就是
root@1cdeb856c365:
- Note: 如果我们需要所有的run的用法可以使用
docker help run Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...] Run a command in a new container -a, --attach=[] Attach to STDIN, STDOUT or STDERR. --add-host=[] Add a custom host-to-IP mapping (host:ip) -c, --cpu-shares=0 CPU shares (relative weight) --cap-add=[] Add Linux capabilities --cap-drop=[] Drop Linux capabilities --cidfile="" Write the container ID to the file --cpuset="" CPUs in which to allow execution (0-3, 0,1) -d, --detach=false Detached mode: run the container in the background and print the new container ID --device=[] Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc) --dns=[] Set custom DNS servers --dns-search=[] Set custom DNS search domains -e, --env=[] Set environment variables --entrypoint="" Overwrite the default ENTRYPOINT of the image --env-file=[] Read in a line delimited file of environment variables --expose=[] Expose a port from the container without publishing it to your host -h, --hostname="" Container host name -i, --interactive=false Keep STDIN open even if not attached --link=[] Add link to another container in the form of name:alias --lxc-conf=[] (lxc exec-driver only) Add custom lxc options --lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" -m, --memory="" Memory limit (format: <number><optional unit>, where unit = b, k, m or g) --name="" Assign a name to the container --net="bridge" Set the Network mode for the container 'bridge': creates a new network stack for the container on the docker bridge 'none': no networking for this container 'container:<name|id>': reuses another container network stack 'host': use the host network stack inside the container. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. -P, --publish-all=false Publish all exposed ports to the host interfaces -p, --publish=[] Publish a container's port to the host format: ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | containerPort (use 'docker port' to see the actual mapping) --privileged=false Give extended privileges to this container --restart="" Restart policy to apply when a container exits (no, on-failure[:max-retry], always) --rm=false Automatically remove the container when it exits (incompatible with -d) --security-opt=[] Security Options --sig-proxy=true Proxy received signals to the process (even in non-TTY mode). SIGCHLD, SIGSTOP, and SIGKILL are not proxied. -t, --tty=false Allocate a pseudo-TTY -u, --user="" Username or UID -v, --volume=[] Bind mount a volume (e.g., from the host: -v /host:/container, from Docker: -v /container) --volumes-from=[] Mount volumes from the specified container(s) -w, --workdir="" Working directory inside the container
Working with our first container
- 我们来详细的看看,我们在这个shell里面能做什么, root@后面有一系列的ID,其实是
这个新的container的ID,也是它的hostname
root@1cdeb856c365:/# hostname hostname 1cdeb856c365
- hostname也一般会反映在文件/etc/hosts里面
root@1cdeb856c365:/# cat /etc/hosts cat /etc/hosts 172.17.0.2 1cdeb856c365 fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback
- 这个container的网络配置也是完整的: 一个localhost, 一个eth0, 其IP地址为172.17.0.2
root@1cdeb856c365:/# ip a ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 6: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff inet 172.17.0.2/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:2/64 scope link valid_lft forever preferred_lft forever
- 可以查看当前运行的进程
root@1cdeb856c365:/# ps -aux ps -aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.1 18168 3240 ? Ss 12:06 0:00 /bin/bash root 23 0.0 0.1 15568 2092 ? R+ 12:21 0:00 ps -aux
- 还能安装文件
root@1cdeb856c365:/# apt-get install vim apt-get install vim Reading package lists... Done Building dependency tree Reading state information... Done The following extra packages will be installed: libgpm2 libpython2.7 libpython2.7-minimal libpython2.7-stdlib vim-runtime Suggested packages: gpm ctags vim-doc vim-scripts The following NEW packages will be installed: libgpm2 libpython2.7 libpython2.7-minimal libpython2.7-stdlib vim vim-runtime 0 upgraded, 6 newly installed, 0 to remove and 0 not upgraded. Need to get 9083 kB of archives. After this operation, 42.9 MB of additional disk space will be used. Do you want to continue? [Y/n]
- 如果你不想使用这个container了以后,就输入exit,然后这个container就stop运行了
可以通过docker ps -a(不加-a就只显示running的container)来查看所有的container,
以及他们的状态
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2eb46e8ca9ff dockerfile/ubuntu-desktop:latest "bash -c 'vncserver 33 hours ago Exited (0) 22 minutes ago 0.0.0.0:5901->5901/tcp determined_einstein a7c56bda446d creack/firefox-vnc:latest "x11vnc -forever -us 33 hours ago Exited (0) 22 minutes ago 0.0.0.0:49153->5900/tcp jolly_fermat 1cdeb856c365 ubuntu:14.04 "/bin/bash" 5 days ago Exited (0) 18 seconds ago cocky_yonath
- docker ps -l是上一次运行的container,非常好用
docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2eb46e8ca9ff dockerfile/ubuntu-desktop:latest "bash -c 'vncserver 33 hours ago Exited (0) 23 minutes ago 0.0.0.0:5901->5901/tcp determined_einstein
Container naming
- ps -a的最后一行就是NAMES, 如果你在创建container的时候输入名字,这个名字就是
随机的, 我们可以使用–name来"取名字"
> docker run --name terminal_test -i -t ubuntu /bin/bash > docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24497ca19cb1 ubuntu:14.04 "/bin/bash" 39 seconds ago Exited (0) 33 seconds ago terminal_test
Staring a stopped container
- 一旦你exit, 这个docker的status就是Exited了,所以你得start(或者restart)它
> docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24497ca19cb1 ubuntu:14.04 "/bin/bash" 39 seconds ago Exited (0) 33 seconds ago terminal_test > docker start terminal_test terminal_test > docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24497ca19cb1 ubuntu:14.04 "/bin/bash" 2 minutes ago Up 11 seconds terminal_test
Attaching to a container
- 一旦这个container进入了start的状态,那么下一步就是attach到它,所以我们又可以
进入它的bash命令行了
docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24497ca19cb1 ubuntu:14.04 "/bin/bash" 2 minutes ago Up 11 seconds terminal_test docker attach terminal_test root@24497ca19cb1:/# hostname hostname 24497ca19cb1
Creating daemonized containers
- 一般来说,在linux上面, 我们需要创建interactive container的需求,远不如创建后台
运行的longer-running container的需求多, 这个时候是使用参数-d
sudo docker run --name daemon_dave -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done" 1d1dd2f1477189f9d2c1d7acc0b382a1e8af5d0f6dcc5b46ab6b22aa7066c328 docker ps -l CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1d1dd2f14771 ubuntu:14.04 "/bin/sh -c 'while t 4 seconds ago Up 3 seconds daemon_dave
- 刚才的时候,我们是有interactive的shell的,所以attach了以后,就立马联系到terminal 而这里没有terminal,我们就返回新创建的container的ID而已
Seeing what's happening inside our container
- 我可以使用logs命令来查看,terminal里面已经输出了什么. 这个命令的结果是不变的
docker logs daemon_dave hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world hello world
- 我们还可以像tail -f 一样, 使用log -f查看动态的文件改动
docker logs -f daemon_dave hello world hello world hello world hello world hello world hello world ...
- –tail参数可以查看某些行的信息
docker logs --tail 3 daemon_dave hello world hello world hello world
- 参数-t是加上时间戳
docker logs -t --tail 3 daemon_dave 2015-03-22T12:52:04.366423061Z hello world 2015-03-22T12:52:05.376884111Z hello world 2015-03-22T12:52:06.387534534Z hello world
Inspecting the container's processes
- 我们也可以使用top命令来查看container里面的process情况
docker top daemon_dave PID USER COMMAND 1110 root /bin/sh -c while true; do echo hello world; sleep 1; done 2143 root sleep 1
Stopping a daemonized container
- 杀掉一个container的方法就是:
- docker stop (发送SIGTERM signal)
- docker kill (发送SIGKILL signal)
- 下面是stop的例子(注意docker ps -n x是查看最近x个container的情况)
docker stop daemon_dave daemon_dave docker ps -n 3 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1d1dd2f14771 ubuntu:14.04 "/bin/sh -c 'while t 20 minutes ago Exited (-1) 34 seconds ago daemon_dave 24497ca19cb1 ubuntu:14.04 "/bin/bash" 31 minutes ago Exited (0) 21 minutes ago terminal_test 2eb46e8ca9ff dockerfile/ubuntu-desktop:latest "bash -c 'vncserver 33 hours ago Exited (0) 57 minutes ago 0.0.0.0:5901->5901/tcp determined_einstein
Finding out more about our container
- 使用inspect会得到更多关于container的信息, 以json数组的形式返回
docker inspect daemon_dave [{ "Args": [ "-c", "while true; do echo hello world; sleep 1; done" ], "Config": { "AttachStderr": false, "AttachStdin": false, "AttachStdout": false, "Cmd": [ "/bin/sh", "-c", "while true; do echo hello world; sleep 1; done" ], "CpuShares": 0, "Cpuset": "", "Domainname": "", "Entrypoint": null, "Env": [ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ], "ExposedPorts": null, "Hostname": "1d1dd2f14771", "Image": "ubuntu", "Memory": 0, ... } ]
- 当然了不是每个人都会使用Emacs的shell,如果我们想知道其中某些部分的信息, 我们
可以使用-f(–format)参数来取得一部分的信息
docker start daemon_dave daemon_dave docker inspect --format '{{.NetworkSettings.IPAddress}}' daemon_dave 172.17.0.7 docker inspect --format '{{.State.Running}}' daemon_dave true
- 我们还可以同时inspect两个container, 如果不加format就是返回一个json数组,不过
成员不再是一个,而是两个
docker inspect --format '{{.State.Running}}' daemon_dave terminal_test true false
Deleting a container
- 我们使用rm命令来删除container,但是container必须是stop状态的
docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1d1dd2f14771 ubuntu:14.04 "/bin/sh -c 'while t 31 minutes ago Up 3 minutes daemon_dave 24497ca19cb1 ubuntu:14.04 "/bin/bash" 42 minutes ago Exited (0) 33 minutes ago terminal_test 2eb46e8ca9ff dockerfile/ubuntu-desktop:latest "bash -c 'vncserver 34 hours ago Exited (0) About an hour ago 0.0.0.0:5901->5901/tcp determined_einstein a7c56bda446d creack/firefox-vnc:latest "x11vnc -forever -us 34 hours ago Exited (0) About an hour ago 0.0.0.0:49153->5900/tcp jolly_fermat 1cdeb856c365 ubuntu:14.04 "/bin/bash" 5 days ago Exited (0) 46 minutes ago cocky_yonath 5273e0466f56 dockerui/dockerui:latest "./dockerui" 6 days ago Exited (0) 5 days ago 0.0.0.0:9000->9000/tcp ecstatic_mcclintock docker stop daemon_dave daemon_dave docker rm daemon_dave daemon_dave docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24497ca19cb1 ubuntu:14.04 "/bin/bash" 42 minutes ago Exited (0) 33 minutes ago terminal_test 2eb46e8ca9ff dockerfile/ubuntu-desktop:latest "bash -c 'vncserver 34 hours ago Exited (0) About an hour ago 0.0.0.0:5901->5901/tcp determined_einstein a7c56bda446d creack/firefox-vnc:latest "x11vnc -forever -us 34 hours ago Exited (0) About an hour ago 0.0.0.0:49153->5900/tcp jolly_fermat 1cdeb856c365 ubuntu:14.04 "/bin/bash" 5 days ago Exited (0) 46 minutes ago cocky_yonath 5273e0466f56 dockerui/dockerui:latest "./dockerui" 6 days ago Exited (0) 5 days ago 0.0.0.0:9000->9000/tcp ecstatic_mcclintock
- 还有一个命令特别厉害可以删除所有的container
> docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 24497ca19cb1 ubuntu:14.04 "/bin/bash" 42 minutes ago Exited (0) 33 minutes ago terminal_test 2eb46e8ca9ff dockerfile/ubuntu-desktop:latest "bash -c 'vncserver 34 hours ago Exited (0) About an hour ago 0.0.0.0:5901->5901/tcp determined_einstein a7c56bda446d creack/firefox-vnc:latest "x11vnc -forever -us 34 hours ago Exited (0) About an hour ago 0.0.0.0:49153->5900/tcp jolly_fermat 1cdeb856c365 ubuntu:14.04 "/bin/bash" 5 days ago Exited (0) 46 minutes ago cocky_yonath 5273e0466f56 dockerui/dockerui:latest "./dockerui" 6 days ago Exited (0) 5 days ago 0.0.0.0:9000->9000/tcp ecstatic_mcclintock > docker rm `docker ps -a -q` 24497ca19cb1 2eb46e8ca9ff a7c56bda446d 1cdeb856c365 5273e0466f56 docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Chapter 4: Working with Docker images and repositories
What is a Docker image?
- Docker image是由多个filesystem layer组成的.最底层的filesystem是bootfs(也就 相当于Linux分区里面的/boot)
- bootfs的上面一层是rootfs
- TODO
Listing Docker images
- 列出docker所有的images的方法如下
> docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu trusty d0955f21bf24 2 weeks ago 188.3 MB ubuntu trusty-20150320 d0955f21bf24 2 weeks ago 188.3 MB ubuntu 14.04 d0955f21bf24 2 weeks ago 188.3 MB ubuntu 14.04.2 d0955f21bf24 2 weeks ago 188.3 MB ubuntu latest d0955f21bf24 2 weeks ago 188.3 MB ubuntu precise 9c5e4be642b7 2 weeks ago 131.9 MB ubuntu precise-20150320 9c5e4be642b7 2 weeks ago 131.9 MB ubuntu 12.04 9c5e4be642b7 2 weeks ago 131.9 MB ubuntu 12.04.5 9c5e4be642b7 2 weeks ago 131.9 MB creack/firefox-vnc latest a41e7b939b8a 23 months ago 557.6 MB
- 首先我们注意到的是我们列出image,但是第一行确实repository. 我们可以把repository 理解为一类image的集合
- repository是建立在不同的registry上面的(但是默认的都是Docker Hub,我们也就不 再考虑其他registry了)
- 可以看到,我们有两种image集合(repository):
- 类似ubuntu这种image是top-level repository, 是Docker Inc管理,由相应vender 提供的. 这种image具有公信力.
- 类似creack/firefox-vnc是由一个username=> creack提供的名字叫做firefox-vnc 的image. 叫做user repository, 当然这个username是Docker Hub上面的username
- 同一类image(repository)里面,区分不同版本的方法是:tag. 比如这里ubuntu
repository就有很多tag:
- 14.04
- 14.04.2
- trusty
- 12.04
- 12.04.5
- precise
- 除了TAG以外,我们还发现了Image ID, 而且我们发现所谓的14.04, 14.04.2, trusty等 等都是一个Image ID, 这也就说明了一个问题,这些tag虽然不同,但是指的缺是同一个 image. 好比git也是可以给commit打tag的,不同tag也可以打给同一个commit, 但是ID 是唯一的!
- 既然已经类比了git,那么我们就类比多一点(以后会发现相似的地方更多):
- docker repository <==> git repository
- docker image <==> git commit
- docker image id <==> git commit hash id
- docker tag <==> git tag
Pulling images
- 我们可以使用pull command来更新repository(git也是使用git pull来<rep>更新某个
repository)
docker pull fedora
Searching for images
- 当然我们可以搜索image啦, 所谓搜索image,其实叫做搜索repository更合适,因为其实
github搜索项目名字,搜索的其实也就是repository的列表. 而我们这里搜索出来的其
实就是repository的列表
docker search puppet NAME DESCRIPTION STARS OFFICIAL AUTOMATED devopsil/puppet Dockerfile for a container with puppet ins... 6 [OK] layerworx/puppetmaster Standard dockerized Puppetmaster server bu... 5 [OK] macadmins/munki-puppet Basic munki nginx image with Puppet used f... 5 [OK] devopsil/puppet-yum 4 [OK] layerworx/puppet A Puppet enabled container running the 3.7... 3 [OK] macadmins/puppetmaster Simple puppetmaster based on CentOS 6 3 [OK] rfkrocktk/puppet 2 [OK] simpledrupalcloud/puppet 1 [OK] devopsil/puppetmaster 1 [OK] lukasz/docker-puppet-openssl-nginx This image is derived from https://index.d... 1 [OK] scrothers/puppet 1 [OK] farodin91/puppet 0 [OK] razic/puppet 0 [OK] kassis/puppet-spec 0 [OK] m0ikz/puppet 0 [OK] solict/provisionous-puppet-centos CentOS provisions with Puppet included 0 [OK] solict/provisionous-puppet-debian Debian provisions with Puppet included 0 [OK] solict/provisionous-puppet-ubuntu Ubuntu provisions with Puppet included 0 [OK] muccg/puppet-base Base images that use puppet and librarian-... 0 [OK] jeyk/puppet 0 [OK] fr3nd/puppet 0 [OK] pataquets/puppet 0 [OK] pmoust/puppet Puppet docker image based on Ubuntu 14.04 ... 0 [OK] viljaste/puppet 0 [OK] vmule/puppet-apt 0 [OK]
- 我们来下载其中一个image集合(repository),如下
docker@boot2docker:~$ docker search jamtur01/puppetmaster NAME DESCRIPTION STARS OFFICIAL AUTOMATED jamtur01/docker-puppetmaster 1 [OK] jamtur01/puppetmaster 0 docker@boot2docker:~$ docker pull jamtur01/puppetmaster Pulling repository jamtur01/puppetmaster 99200e07340a: Download complete 511136ea3c5a: Download complete 3e76c0a80540: Download complete be88c4c27e80: Download complete bfab314f3b76: Download complete e809f156dc98: Download complete 0ef6ede68afa: Download complete Status: Downloaded newer image for jamtur01/puppetmaster:latest
- 然后,我们可以看到已经在image里面了
docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu trusty d0955f21bf24 2 weeks ago 188.3 MB ubuntu trusty-20150320 d0955f21bf24 2 weeks ago 188.3 MB ubuntu 14.04 d0955f21bf24 2 weeks ago 188.3 MB ubuntu 14.04.2 d0955f21bf24 2 weeks ago 188.3 MB ubuntu latest d0955f21bf24 2 weeks ago 188.3 MB ubuntu precise 9c5e4be642b7 2 weeks ago 131.9 MB ubuntu precise-20150320 9c5e4be642b7 2 weeks ago 131.9 MB ubuntu 12.04 9c5e4be642b7 2 weeks ago 131.9 MB ubuntu 12.04.5 9c5e4be642b7 2 weeks ago 131.9 MB jamtur01/puppetmaster latest 99200e07340a 10 months ago 312.4 MB creack/firefox-vnc latest a41e7b939b8a 23 months ago 557.6 MB
Building our own images
- 创建一个image的办法有两个:
- docker commit (已经被弃用)
- docker build with Dockerfile
Building images with a Dockerfile
- Dockerfile就是专门为docker专门准备的一门DSL
- 我们来先看看第一个例子