Docker简介
Docker 镜像(image)
镜像是一个可执行的包,它包含了所有用来执行某个软件所需要的内容,包括代码,运行时,库,环境变量,还有配置文件。
Docker容器(container)
容器是镜像运行时的实例–镜像执行时,在内存中变成的样子。容器可以原生地运行在Linux中,它和其余的容器共享本地Linux主机的内核。docker ps,查看正在运行的容器;docker stop,中断运行的容器。每个容器都分别独立在进程中运行,占用的内存不超过任何其他可执行文件。
虚拟机VS容器
传统的虚拟化技术,比如 VMWare, KVM, Xen,目标是创建完整的虚拟机。为了运行应用,除了部署应用本身及其依赖(通常几十 MB),还得安装整个操作系统(几十 GB)。而对于容器来说,所有的容器共享同一个 Host OS,这使得容器在体积上要比虚拟机小很多。另外,启动容器不需要启动整个操作系统,所以容器部署和启动速度更快,开销更小,也更容易迁移。
Docker仓库
Docker仓库用来保存镜像。Docker仓库分为公有仓库和私有仓库。
公有的仓库有Docker Hub等。Docker Hub(https://hub.docker.com/) 是 Docker 为公众提供的托管 Registry,上面有很多现成的 image,为 Docker 用户提供了极大的便利。http://Quay.io(https://quay.io/)是另一个公共托管 Registry,提供与 Docker Hub 类似的服务。
出于对速度或安全的考虑,用户也可以创建自己的私有 Registry。后面我们会学习如何搭建私有 Registry。
Docker安装
根据官网直接下载对应的Docker版本。https://docs.docker.com/install/
测试Docker
运行docker --version查看docker的版本
docker --version
Docker version 18.09.2, build 6247962
运行docker info可以查看更多关于docker安装的细节。
docker info
使用Dockerfile定义容器
准备Dockerfile文件
在新创建的目录下,创建Dockerfile文件。Dockerfile文件定义了在容器环境中进行什么操作,比如对网络接口资源的访问,比如对磁盘驱动的访问。后续,可以根据Dockerfile文件,创建新的镜像
# 表明将官方 Python 运行时用作父镜像。后续可以根据自己已有的镜像作为父镜像构建
FROM python:2.7-slim
# 表明将工作目录设置为 /app。为后续的RUN,CMD等操作指令配置工作目录,可以使用多个WORKDIR指令。
WORKDIR /app
# 将当前目录内容复制到位于 /app 中的容器中。容器的指定路径必须是绝对路径,如果不存在会自动创建对应目录。
ADD . /app
# 安装 requirements.txt 中指定的任何所需软件包
RUN pip install -r requirements.txt
# 表示本地端口 80 可供此容器外的环境使用。需要在docker run的时候使用-p或者-P选项生效
EXPOSE 80
# 定义环境变量
ENV NAME World # 等同于NAME=“World”
# 在容器启动时运行 app.py
CMD ["python", "app.py"]
上述Dockerfile文件表示,会将当前目录内容,添加到/app中的容器。当前目录中存在requirements.txt文件和app.py文件同时需要根据自己的需求创建。下面表明同一目录下的文件情况
$ ls
Dockerfile app.py requirements.txt
构建
通过docker build 创建Docker镜像。-t表示镜像标签(tag)。注意后面有个.,表明1以当前文件夹下的Dockerfile文件进行构建
docker build -t friendlyhello .
除了上面介绍的通过Dockerfile构建镜像之外,还有一种构建办法。就是使用docker commit命令,通过容器构建镜像。docker commit创建镜像有三个过程,先运行容器,再对容器内容进行修改,最后commit将容器保存为新的镜像。
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
-p, --pause Pause container during commit (default true)
镜像的共享
登录镜像
docker login
pull镜像
docker pull默认从官方仓库获取,也可从似有仓库获取,需要指定位置。例如从myregistry.local仓库的5000端口获取test-image镜像。
docker pull myregistry.local:5000/testing/test-image
获取ubuntu官方镜像
docker pull ubuntu
标记镜像
将本地镜像(local image)与镜像仓库(registry)中关联起来的标记是:username/repository:tag
tag实际上是可选的,但是一般推荐写上。例如:
docker tag <image> username/repository:tag
docker tag friendlyhello gordon/get-started:part2
push(上传)镜像
上传已经标记好的镜像到仓库中。
docker push username/repository:tag
创建并运行容器
docker run运行容器,其中参数i表示交互模式。t表示分配一个伪tty。
docker run -it <image id或者image name>
docker run -i -t ubuntu:14.04
docker run运行容器的时候,最好指定一下–shm-size,单位是字节,因为默认是docker容器中默认是64M,很多软件无法正常工作,可以设置为–shm-size=59g。这个/dev/shm是linux下一个非常有用的目录,这个目录(共享内存目录)在内存里而不是硬盘上。
swap 和shm的区别
swap(交换内存)是一个文件,是使用硬盘空间的一部分作为物理内存来扩展RAM空间的,虽然是物理硬盘的一部分,但是仍然属于RAM,并且属于易失性存储,重启机器会使数据丢失;空间大小在一般情况下,swap的空间大小设置为物理内存的两倍大小;docker中的swap对应于物理机器linux系统中的swap
shm(共享内存)在机器上挂载名可以是dev/shm,也可以是tmpfs;是将虚拟内存的一部分挂载为临时文件系统,用于应用程序的加速,原理是允许其中的数据被不同的应用程序访问;在tmpfs中创建的文件很自然地也就创建在了虚拟内存中,因此其存储性质同swap,属于易失性存储;在docker中使用–shm-size命令挂载的分区是/dev/shm,可以在docker的命令行中使用df -h命令查看;同时也能看到本机的物理机器上的tmpfs分区;
区别总结
- tmpfs使用内存空间而swap使用物理存储空间
- swap有经验意义上推荐的大小,而tmpfs没有;tmpfs的大小与所运行系统的目的有关
- tmpfs可以使当前运行系统中的应用程序运行的更快,而swap是缓解系统物理内存压力的
- wap空间满了表明系统正在高负荷运转,会造成性能下降甚至死机;而tmpfs满了以后并不一定有上面的情况
- tmpfs是作为“增强型”功能出现的,而swap是必须有的功能
为了避免踩坑,还需要看情况设置ulimit参数,更改docker容器资源限制。
详细参考官网docker run的参数:https://docs.docker.com/engine/reference/commandline/run/#set-ulimits-in-container—ulimit
以及ulimit的使用https://www.ibm.com/developerworks/cn/linux/l-cn-ulimit/index.html
一般加上 --name,指定容器的名称。
踩坑: 默认启动的容器磁盘大小只有10G,随着容器变大,就会出现no space left on device的错误。可以设置为:–storage-opt size=100G
还有个常用选项:–rm,如果只是在开发调试过程中短期运行,其用户数据并无保留的必要,因而可以在容器启动时设置–rm选项,这样在容器退出时就能够自动清理容器内部的文件系统。automatically remove the container when it exits. 不支持docker run -d 启动的容器。
最终我在服务器上运行命令如下:
docker run -it --shm-size=59g --ulimit memlock=-1 --ulimit stack=67108864 --storage-opt size=100G --name=‘xinming’ imageID
常用命令
docker images
列出当前系统镜像
docker rmi
删除一个或者多个镜像
Usage: docker rmi [OPTIONS] IMAGE [IMAGE...]
Remove one or more images
Options:
-f, --force Force removal of the image
--no-prune Do not delete untagged parents
docker info
Server Version: 1.12.6 # 服务器版本:1.12.6
Storage Driver: devicemapper # 存储驱动程序:devicemapper
Pool Name: docker-8:3-2097465-pool # 池名称:docker-8:3-2097465-pool
Pool Blocksize: 65.54 kB # Pool Blocksize:65.54 kB
Base Device Size: 107.4 GB # 基本设备大小:107.4 GB
Backing Filesystem: ext4 # 支持文件系统:ext4
Data file: /dev/loop0 # 数据文件:/ dev / loop0
Metadata file: /dev/loop1 # 元数据文件:/ dev / loop1
Data Space Used: 5.352 GB # 使用的数据空间:5.352 GB
Data Space Total: 107.4 GB # 数据空间总计:107.4 GB
Data Space Available: 10.04 GB # 可用数据空间:10.04 GB
Metadata Space Used: 7.229 MB # 使用的元数据空间:7.229 MB
Metadata Space Total: 2.147 GB # 元数据空间总计:2.147 GB
Metadata Space Available: 2.14 GB # 可用元数据空间:2.14 GB
Thin Pool Minimum Free Space: 10.74 GB # 精简池最小可用空间:10.74 GB
Udev Sync Supported: true # Udev Sync支持:true
Deferred Removal Enabled: true # 延迟删除已启用:true
Deferred Deletion Enabled: true # 延迟删除已启用:true
Deferred Deleted Device Count: 0 # 延迟删除的设备数:0
Data loop file: /var/lib/docker/devicemapper/devicemapper/data # 数据循环文件:/ var / lib / docker / devicemapper / devicemapper / data
WARNING: Usage of loopback devices is strongly discouraged for production use. Use `--storage-opt dm.thinpooldev` to specify a custom block storage device. # 警告:强烈建议不要使用环回设备进行生产。使用`--storage-opt dm.thinpooldev`指定自定义块存储设备。
Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata # 元数据循环文件:/ var / lib / docker / devicemapper / devicemapper / metadata
Library Version: 1.02.107-RHEL7 (2015-10-14) 版本:1.02.107-RHEL7(2015-10-14)
Logging Driver: journald # 日志驱动程序:journald
Cgroup Driver: systemd # Cgroup驱动程序:systemd
Plugins: # 插件:
Volume: local # 存储卷:本地
Network: bridge host null overlay # 网络:桥接主机空覆盖
Swarm: inactive # Swarm:不活跃
Runtimes: docker-runc runc # 运行时:docker-runc runc
Default Runtime: docker-runc # 默认运行时:docker-runc
Security Options: seccomp # 安全选项:seccomp
Kernel Version: 3.10.0-327.el7.x86_64 # 内核版本:3.10.0-327.el7.x86_64
Operating System: CentOS Linux 7 (Core) # 操作系统:CentOS Linux 7(核心)
OSType: linux # 系统类别:linux
docker容器
docker start
运行停止的容器。在容器内执行exit后,容器就会退出并停止!
docker stop 容器名/id
docker start 容器名/id(已经停止的容器)
docker start ContainerID
docker ps
列出正在运行的容器。加上参数-a后,就会列出所有的容器,还包括关闭的容器。-s会显示所有的文件大小
docker kill
退出容器
退出容器:
exit
注意:这个命令退出容器,会使容器就变成Exited的状态,这样容器就会关闭。
或者
Ctrl+P+Q
如果要正常退出不关闭容器,请按Ctrl+P+Q进行退出容器
docker rm
删除一个或者多个容器。必须停止容器,才能删掉。
进入容器
创建进入容器
创建一个守护态的Docker容器,根据docker镜像。
docker run -itd ubuntu:14.04 /bin/bash
容器开启之后,通过下面的命令进入该容器。
登陆正在运行的容器
attach方式
docker attach ContainerID
这个命令始终会进入原来创建的终端,因此,该命令有一个问题。当多个窗口同时使用该命令进入该容器时,所有的窗口都会同步显示。如果有一个窗口阻塞了,那么其他窗口也无法再进行操作。因为这个原因,所以docker attach命令不太适合于生产环境,平时自己开发应用时可以使用该命令。
ssh方式
相信大家第一个想到的就是ssh。在镜像(或容器)中安装SSH Server,这样就能保证多人进入
容器且相互之间不受干扰了。但是使用了Docker容器之后不建议使用ssh进入到Docker容器内。关于为什么不建议使用,请参考如下文章:
为什么不需要在 Docker 容器中运行 sshd
exec方式 (推荐)
docker exec -it Containerid command
例如下面的命令。
docker exec -it 775c7c9ee1e1 /bin/bash
使用docker exec -h查看手册后,能够看到相应的参数介绍
Options:
-d, --detach Detached mode: run command in the background
–detach-keys string Override the key sequence for detaching a container
-e, --env list Set environment variables
-i, --interactive Keep STDIN open even if not attached
–privileged Give extended privileges to the command
-t, --tty Allocate a pseudo-TTY
-u, --user string Username or UID (format: <name|uid>[:<group|gid>])
-w, --workdir string Working directory inside the container
exec 的方式优点:这样就会创建一个新的终端。不受原终端运行的影响。所以如果在此终端执行exit命令,也不会使该容器停止。
杀掉正在运行的一个或者多个容器
docker kill container
Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
Options:
-f, --force Force the removal of a running container (uses SIGKILL)
-l, --link Remove the specified link
-v, --volumes Remove the volumes associated with the container
参考:
Docker官方_get-started
Docker中文官方_get-startde
非常详细的Docker学习笔记_CSDN
每天五分钟玩转Docker容器技术_阿里云云栖社区