Docker(一)
容器与虚拟机
- 容器能与主机的操作系统共享资源,因而它的效率高出一个数量级。启动和停止容器,只需在一瞬间。相比直接在主机上运行程序,容器的性能损耗非常低,甚至是零损耗。
- 容器具有可移植性
- 容器是轻量的,意味着开发者能同时运行数十个容器,新功能模拟分布式系统在真实运行环境下的情况。
- 对于最终用户及开发者而言,用户可以下载并执行复杂的应用程序,而无需花费大量时间在配置和安装的问题上,也无需要担心对系统本身的改动。
jason@Jason ~ % docker run debian echo "Hello World"
Unable to find image 'debian:latest' locally
latest: Pulling from library/debian
756975cb9c7e: Downloading
latest: Pulling from library/debian
756975cb9c7e: Pull complete
Digest: sha256:e2cc6fb403be437ef8af68bdc3a89fd58e80b4e390c58f14c77c466002391193
Status: Downloaded newer image for debian:latest
Hello World
jason@Jason ~ %
清理已经停止的容器
docker rm -v $(docker ps -qa -f status=exited)
docker run 时加上 --rm
参数,它的作用是当容器退出时,容器和相关的文件系统会被一并删除
jason@Jason ~ % docker run -it --name cowsay --hostname cowsay debian bash
root@cowsay:/#
root@cowsay:/# apt-get update
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://security.debian.org/debian-security buster/updates/main amd64 Packages [254 kB]
Get:3 http://deb.debian.org/debian buster InRelease [121 kB]
Get:4 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Get:5 http://deb.debian.org/debian buster/main amd64 Packages [7906 kB]
Get:6 http://deb.debian.org/debian buster-updates/main amd64 Packages [7856 B]
Fetched 8407 kB in 4s (2279 kB/s)
Reading package lists... Done
root@cowsay:/#
root@cowsay:/# apt-get install -y cowsay fortune
docker commit
把容器转成镜像,无论容器是在运行中还是在停止状态都可以
jason@Jason ~ % docker commit cowsay test/cowsayimage
sha256:15f184e7042102b68e25b774fe3bb65464d57c543df78d890079e180834e71f7
jason@Jason ~ %
jason@Jason ~ % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/cowsayimage latest 15f184e70421 About a minute ago 181MB
jason@Jason ~ %
jason@Jason ~ %
根据生成的镜像创建容器
jason@Jason ~ % docker run --rm test/cowsayimage /usr/games/cowsay "Moo"
_____
< Moo >
-----
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
jason@Jason ~ %
Dockerfile
jason@Jason ~ % mkdir cowsay
jason@Jason ~ % cd cowsay
jason@Jason cowsay % touch Dockerfile
jason@Jason cowsay %
在 Dockerfile
中写入以下内容:
FROM debian
RUN apt-get update && apt-get install -y cowsay fortune
FROM
指令指定初始镜像,Dockerfile
一定要有FROM
指令作为第一个非注释指令。
RUN
指令指定的 shell
命令,是将要在镜像里执行的。
jason@Jason cowsay % docker build -t test/cowsay-dockerfile .
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM debian
---> ef05c61d5112
Step 2/2 : RUN apt-get update && apt-get install -y cowsay fortune
---> Running in 9c06a2bf1acc
...
Setting up cowsay (3.03+dfsg2-6) ...
Processing triggers for libc-bin (2.28-10) ...
Removing intermediate container 9c06a2bf1acc
---> 559b7924217e
Successfully built 559b7924217e
Successfully tagged test/cowsay-dockerfile:latest
jason@Jason cowsay %
jason@Jason cowsay % docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
test/cowsay-dockerfile latest 559b7924217e 2 minutes ago 181MB
test/cowsayimage latest 15f184e70421 11 minutes ago 181MB
debian latest ef05c61d5112 2 weeks ago 114MB
jason@Jason cowsay %
jason@Jason cowsay % docker run --rm test/cowsay-dockerfile /usr/games/cowsay "Moo"
_____
< Moo >
-----
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
jason@Jason cowsay %
联合文件系统
,允许多个文件系统叠加,并表现为一个单一的文件系统。
文件夹中的文件可以来自多个文件系统,但如果有两个文件的路径完全相,最后挂载的文件则会覆盖较早前挂载的文件。
Docker 的镜像由多个不同的层(layer)组成,每一个层都是一个只读的文件系统。
Dockerfile 里的每个指令都会创建一个新的层,而这个层位于前一个层之上。
当一个镜像被转化成一个容器时(docker run 或 docker create),Docker引擎会在镜像之上添加一个处于最上层的可读写文件系统(同时还会对一些配置进行初始化,如IP地址,名称,ID等)。
由于不必要的层会使镜像变得臃肿,所以Dockerfile
会把多个UNIX
命令放在同一个 RUN
指令中,以减少层的数量。
容器可以处于几种状态:created
,restarting
,running
,paused
,exited
restarting
状态比较少见,当 Docker 引擎尝试重启一个启动失败的容器时,它才会出现。
Dockerfile
的 ENTRYPOINT
指令,可以让用户更易于使用这个镜像:
FROM debian
RUN apt-get update && apt-get install -y cowsay fortune
ENTRYPOINT ["/usr/games/cowsay"]
jason@Jason cowsay % docker build -t test/cowsay-dockerfile .
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM debian
---> ef05c61d5112
Step 2/3 : RUN apt-get update && apt-get install -y cowsay fortune
---> Using cache
---> 559b7924217e
Step 3/3 : ENTRYPOINT ["/usr/games/cowsay"]
---> Running in 4f8163ac1aa0
Removing intermediate container 4f8163ac1aa0
---> 6015f6f41264
Successfully built 6015f6f41264
Successfully tagged test/cowsay-dockerfile:latest
jason@Jason cowsay %
jason@Jason cowsay % docker run --rm test/cowsay-dockerfile "Moo"
_____
< Moo >
-----
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
jason@Jason cowsay %
可以将 ENTRYPOINT
指定为一个脚本
jason@Jason cowsay % touch entrypoint.sh
jason@Jason cowsay % chmod +x entrypoint.sh
jason@Jason cowsay %
entrypoint.sh
#!/bin/bash
if [ $# -eq 0 ]; then
/usr/games/fortune | /usr/games/cowsay
else
/usr/games/cowsay "$@"
fi
Dockerfile
FROM debian
RUN apt-get update && apt-get install -y cowsay fortune
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
jason@Jason cowsay % docker build -t test/cowsay-dockerfile .
Sending build context to Docker daemon 3.072kB
Step 1/4 : FROM debian
---> ef05c61d5112
Step 2/4 : RUN apt-get update && apt-get install -y cowsay fortune
---> Using cache
---> 559b7924217e
Step 3/4 : COPY entrypoint.sh /
---> dab9fcb602fb
Step 4/4 : ENTRYPOINT ["/entrypoint.sh"]
---> Running in 725a2cec481f
Removing intermediate container 725a2cec481f
---> a699a0024aee
Successfully built a699a0024aee
Successfully tagged test/cowsay-dockerfile:latest
jason@Jason cowsay %
jason@Jason cowsay %
jason@Jason cowsay % docker run --rm test/cowsay-dockerfile
_________________________________________
/ Don't read any sky-writing for the next \
\ two weeks. /
-----------------------------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
jason@Jason cowsay %
jason@Jason cowsay %
jason@Jason cowsay % docker run --rm test/cowsay-dockerfile Hello Moo
___________
< Hello Moo >
-----------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
jason@Jason cowsay %
在次cowsay镜像上传到 DockerHub上时,在 Dockerfile 内加入 MAINTAINER
指令,给镜像设定作者的联系信息:
FROM debian
MAINTAINER Jason Zhang <jason@zhang.com>
RUN apt-get update && apt-get install -y cowsay fortune
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
提交到 DockerHub
docker build -t jason/cowsay .
docker push jason/cowsay
指定标签:
docker build -t jason/cowsay:stable .
镜像的命名空间:
- 镜像名称以字符串和/开头,如:jason/cowsay,那么它属于用户命名空间
- 如 debian 或ubuntu 的名称,不包含前缀或/,属于根命名空间。
- 以主机名或IP开头的名称,代表该镜像来自第三方的寄存服务。
使用官方的镜像
jason@Jason ~ % docker pull redis
Using default tag: latest
latest: Pulling from library/redis
852e50cd189d: Pull complete
76190fa64fb8: Pull complete
9cbb1b61e01b: Pull complete
d048021f2aae: Pull complete
6f4b2af24926: Pull complete
1cf1d6922fba: Pull complete
Digest: sha256:5b98e32b58cdbf9f6b6f77072c4915d5ebec43912114031f37fa5fa25b032489
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
jason@Jason ~ %
-d
参数记容器在后台运行
jason@Jason ~ % docker run --name myredis -d redis
44e9cc7b284fb1ced50f6b980acde1a586dee2b2437abdd7195319b1a9d40039
jason@Jason ~ %
再启动一个新的容器来作为 redis-cli 客户端角色,并把两个容器连接上:
jason@Jason ~ % docker run --rm -it --link myredis:redis redis /bin/bash
root@c25960b09515:/data#
root@c25960b09515:/data# redis-cli -h redis -p 6379
redis:6379> ping
PONG
redis:6379> set 'abc' 123
OK
redis:6379> get abc
"123"
redis:6379>
--link
命令可以把容器连接起来。
--link myredis:redis
把新的容器与已存在的myredis
容器连接起来,并且在阐析容器中以redis
作为myredis
容器的主机名。
Docker 通过 数据卷(volume),实现容器与主机,或者容器与其他容器之间轻松共享数据
声明数据卷的两种方法:
第一种:在Dockerfile
中使用 VOLUME
指令
第二种:在执行 docker run
的时候使用 -v
参数
VOLUME /data
或
docker run -v /data test/webserver
默认情况下,目录或文件会挂载在主机的Docker安装目录下
执行docker run
的时候,可以指定用于挂载的主机目录,如:docker run -v /host/dir:/container/dir test/webserver
出于可移植性和安全方面的考虑,主机目录是无法在
Dockerfile
中指定的。
如何为Redis容器做备份呢?假设myredis
容器还在运行中
jason@Jason ~ % docker run --rm -it --link myredis:redis redis /bin/bash
root@e7c04ee79a47:/data# redis-cli -h redis -p 6379
redis:6379> set abc 123
OK
redis:6379> get abc
"123"
redis:6379> save
OK
redis:6379>
redis:6379> exit
root@e7c04ee79a47:/data# exit
exit
jason@Jason ~ %
jason@Jason ~ % docker run --rm --volumes-from myredis -v $(pwd)/backup:/backup debian cp /data/dump.rdb /backup/
jason@Jason ~ %
jason@Jason ~ % ll backup | grep dump
-rw-r--r-- 1 jason staff 104 12 4 18:59 dump.rdb
jason@Jason ~ %
这里-v
参数挂载一个主机上已知的目录,并通过--volumes-from
将新容器连接至redis
数据库目录
停止并删除myredis
容器:
jason@Jason ~ % docker stop myredis
myredis
jason@Jason ~ %
jason@Jason ~ % docker rm -v myredis
myredis
jason@Jason ~ %