docker 基础操作
前言
Docker是一种Linux容器工具集,它是为“构建(build)、交付(ship)和运行(运行)”分布式应用而设计的。
预备知识
什么是容器?
容器就是在隔离的环境运行的一个进程,如果进程停止,容器就会销毁。隔离的环境拥有自己的系统文件,ip地址,主机名等
容器和虚拟化的区别
kvm虚拟化: 需要硬件的支持,需要模拟硬件,可以运行不同的操作系统,启动时间分钟级
开机启动流程:
- bios开机硬件自检
- 根据bios设置的优先启动项 网卡 硬盘 u盘 光驱
- 读取mbr引导 UEFI(gpt分区) mbr硬盘分区信息,内核加载路径
- 加载内核
- 启动第一个进程init systemd
- 系统初始化完成
- 运行服务
容器虚拟化: 不需要硬件的支持。不需要模拟硬件,共用宿主机的内核,启动时间秒级 (没有开机启动流程)
容器:共用宿主机内核,运行服务,损耗少,启动快,性能高
容器的优势:
- 与宿主机使用同一个内核,性能损耗小;
- 不需要指令级模拟;
- 容器可以在CPU核心的本地运行指令,不需要任何专门的解释机制;
- 避免了准虚拟化和系统调用替换中的复杂性;
- 轻量级隔离,在隔离的同时还提供共享机制,以实现容器与宿主机的资源共享。
docker 常用命令
docker容器
- Docker是通过内核虚拟化技术(namespaces及cgroups cpu、内存、磁盘io等)来提供容器的资源隔离与安全保障等。由于Docker通过操作系统层的虚拟化实现隔离,所以Docker容器在运行时,不需要类似虚拟机(VM)额外的操作系统开销,提高资源利用率。 (namespace 资源隔离 cgroups 进程的资源限制)
- docker的主要目标:是"Build,Ship and Run any App,Angwhere",构建,运输,处处运行部署服务,环境问题一次构建,处处运行,docker是一种软件的打包技术
- docker解决了软件和操作系统环境之间的依赖,能够让独立服务或应用程序在不同的环境中,得到相同的运行结果。
注意:
- 构建:做一个docker镜像
- 运输:docker pull
- 运行:启动一个容器
- 每一个容器,他都有自己的系统文件rootfs.
优势:
- docker容器是一种轻量级、可移植、自包含的软件打包技术,使应用程序可以在几乎任何地方以相同的方式运行。
- 开发人员在自己笔记本上创建并测试好的容器,无需任何修改就能够在生产系统的虚拟机、物理服务器或公有云主机上运行。
查看版本:
docker version
显示docker系统信息:
docker info (如果做监控)
docker主要组件有:
- 镜像
- 容器
- 仓库
- 网络
- 存储(数据卷)
镜像操作
搜索镜像: docker search 拉去镜像: docker pull 示例: docker pull centos:6.8 (没有指定版本,默认会下载最新版) docker pull daocloud.io/huangzhichong/alpine-cn:latest 查看镜像: 1、docker image ls 2、docker images 删除镜像: docker rmi [镜像ID] 示例: docker image rm centos:latest 导出镜像: docker image save [镜像] > [导出自定义镜像名] 示例: docker image save centos > docker-centos7.4.tar.gz 导入镜像: docker image load -i [镜像包] 示例: docker image load -i docker-centos7.4.tar.gz
容器操作
查看容器: 1、docker ps 2、docker ps -a 停止: docker stop [容器ID] 终止: docker kill [容器名] 删除容器: 1、docker rm [容器ID] 2、docker rm -f `docker ps -a -q` 启动容器: 1、docker run -d -p 80:80 --name nginx_name[容器名] nginx[镜像名] 参数详情: run 创建并运行一个容器 -d 放在后台 -p 端口映射
--name 指定创建的容器名称(自定义) nginx docker镜像名 2、docker run -it --name centos6 centos:6.9 /bin/bash # 一般-it 都是一起使用: 分配交互式终端 参数详情: -i 交互式操作
-t 终端 --name 指定容器的名字 /bin/bash 放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
进入容器:
1、docker attach [容器ID] # 这种方式进入容器,退出(exit)容器后,容器会停止
2、推荐:docker exec [容器ID] -it /bin/bash # 这种方式退出时,容器正常运行
特别注意:
1、docker 服务启动后, 如果重启了firewalld(防火墙), 那么必须重启docker服务(ststemctl restart docker), 不然会报错
Error response from daemon: driver failed programming external connectivity on endpoint xxxxx ......
更新:(示例更新服务重启设置)
docker update [OPTIONS] CONTAINER [CONTAINER...]
docker update 容器ID --restart=always
注意:(重启策略有四种)
1、no 默认, 不重启
2、always 只要不是手动stop的都会重启
3、on-failure 在容器非正常退出时(退出状态非0),才会重启容器
4、on-failure:3 在容器非正常退出时(退出状态非0),才会重启容器
容器中安装工具:
示例:
1、apt-get update
2、apt-get install vim
容器制作成镜像:(一个启动的容器)
docker commit [容器ID] iamge_name:[版本](自定义)
仓库
借鉴: Docker 私有仓库搭建 - 程序员果果 - 博客园 (cnblogs.com)
在 Docker 中,当我们执行 docker pull xxx 的时候 ,它实际上是从 registry.hub.docker.com 这个地址去查找,这就是Docker公司为我们提供的公共仓库。在工作中,我们不可能把企业项目push到公有仓库进行管理。所以为了更好的管理镜像,Docker不仅提供了一个中央仓库,同时也允许我们搭建本地私有仓库。这一篇介绍registry、harbor两种私有仓库搭建。
1、搭建私有仓库:
Docker 官方提供了一个搭建私有仓库的镜像 registry ,只需把镜像下载下来,运行容器并暴露5000端口,就可以使用了。
docker pull registry:2 docker run -d -v /opt/registry:/var/lib/registry -p 5000:5000 --restart=always --name myregistry registry:2
# --restart=always 如果容器挂了会自动起来
Registry服务默认会将上传的镜像保存在容器的/var/lib/registry,我们将主机的/opt/registry目录挂载到该目录,即可实现将镜像保存到主机的/opt/registry目录了。
浏览器访问http://127.0.0.1:5000/v2,出现下面情况说明registry运行正常。
2. 验证
现在通过push镜像到registry来验证一下。
查看本地镜像:
要通过docker tag将该镜像标志为要推送到私有仓库:
docker tag nginx:latest localhost:5000/nginx:latest
通过 docker push 命令将 nginx 镜像 push到私有仓库中:
docker push localhost:5000/nginx:latest
访问 http://127.0.0.1:5000/v2/_catalog 查看私有仓库目录,可以看到刚上传的镜像了:
下载私有仓库的镜像,使用如下命令:
docker pull localhost:5000/镜像名:版本号
例如
docker pull localhost:5000/nginx:latest
网络操作:
docker 通过iptables来实现的端口映射 指定映射(docker 会自动添加一条iptables规则来实现端口映射): -p 宿主机:容器
示例: -p hostPort:containerPort -p ip:hostPort:containerPort 多个容器都想使用80端口 -p ip::containerPort(随机端口) -p hostPort:containerPort:udp -p 81:80 –p 443:443 可以指定多个-p 随机映射: docker run -P (随机端口)
存储(数据卷)
搬运: Docker 数据卷管理 - 东邪西毒 - 博客园 (cnblogs.com)
Docker中的数据可以存储在类似于虚拟机磁盘的介质中,在Docker中称为数据卷(Data Volume
)。数据卷可以用来存储Docker应用的数据,也可以用来在Docker容器间进行数据共享。
数据卷呈现给Docker容器的形式就是一个目录,支持多个容器间共享,修改也不会影响镜像。使用Docker的数据卷,类似在系统中使用 mount 挂载一个文件系统。
本节中,我们需要依次完成下面几项任务:
- 创建数据卷
- 管理数据卷权限
- 挂载宿主机文件
- 使用数据卷容器共享数据
- 数据卷备份
一、创建数据卷
容器管理实验中我们学习的命令 docker run
用来创建容器,可以在使用改命令时添加 -v
参数,就可以创建并挂载一个到多个数据卷到当前运行的容器中,-v
的作用是将宿主机的一个目录作为容器的数据卷挂载到容器中,使宿主机和容器之间可以共享一个目录,如果本地路径不存在,Docker也会自动创建。
本节实验中,我们挂载2个数据卷到新创建的容器上:
# 创建两个目录 mkdir /tmp/data1 /tmp/data2 # 分别将两个目录挂载到新创建的容器上 docker run -t -i --name shiyanlou -v /tmp/data1:/data1 -v /tmp/data2:/data2 ubuntu /bin/bash
上述命令中 -v
参数可以使用多次,并挂在多个数据卷到容器中。后面的参数信息中冒号前面是宿主机的本地目录,冒号后面是容器中的挂载目录。
使用 docker inspect shiyanlou
查看shiyanlou容器中的数据卷信息:
#docker inspect shiyanlou
进入容器后我们可以查看和使用容器卷,尝试向这个容器卷中写入数据,然后在宿主机中查看是否存在:
可以看到容器中挂载的数据卷具备可写权限,那么如何对数据卷的权限进行管理呢?比如如何创建一个只读的数据卷呢?
二、数据卷权限
挂载的数据卷默认为可读写权限,除非外部文件系统做了特殊限制,在 docker run
的时候也可以执行为只读
权限:
# 创建一个数据卷目录 mkdir /tmp/readonlydata # 以只读的方式挂载到shiyanlouro容器上 docker run -t -i --name shiyanlouro -v /tmp/readonlydata:/rodata:ro ubuntu /bin/bash
上面的命令中参数很简单,ro
表示 readonly
,挂载后的数据卷就是只读权限了,这时候我们再次尝试向数据卷中写入:
除了可以挂载目录之外,文件也可以作为数据卷挂载到容器中。
三、挂载宿主机上的文件
在本实验中,我们想让所有的容器都可以共享宿主机的/etc/apt/sources.list
,从而只需要改变宿主机的apt源就能够影响到所有的容器。
docker run -t -i --name shiyanloufile -v /etc/apt/sources.list:/etc/apt/sources.list:ro ubuntu /bin/bash
如果我们想共享一个数据卷给多个容器怎么办,比如设想一个场景,我们有两个处理上传数据的应用运行在不同的容器中,但需要同时读取同一个文件夹下的文件,此时,最好的方式是使用数据卷容器。
四、数据卷容器
如果需要在多个容器间共享数据,并希望永久保存这些数据,最好的方式是使用数据卷容器,类似于一个提供网络文件共享服务的NFS服务器。
数据卷容器创建方法跟普通容器一样,只需要指定宿主机的一个文件夹作为数据卷即可,使用docker create
命令创建但不启动数据卷容器:
docker create -v /shiyanloudata --name shiyanloudb ubuntu /bin/true # /shiyanloudata 与宿主机无关, 此目录是容器中的目录,没有会自动创建
其他使用该数据卷容器的容器创建时候需要使用--volumes-from
参数,指定该容器名称或ID:
docker run --volumes-from shiyanloudb ...
创建site1和site2两个容器挂载数据卷容器shiyanloudb:
可以连接到这两个容器中对数据卷进行操作,并查看彼此之间是否已经有了共享文件:
五、备份数据卷
继续使用实验四的环境,我们对数据卷容器中的数据进行备份,备份方法:
- 创建一个新的容器
- 挂载数据卷容器
- 挂载宿主机本地目录作为数据卷
- 将数据卷容器的内容备份到宿主机本地目录挂载的数据卷中
- 完成备份操作后容器销毁
请按照上述步骤对数据卷容器shiyanloudb中的数据进行备份:
# 创建备份目录 mkdir /tmp/backup # 创建备份容器 docker run --rm --volumes-from shiyanloudb -v /tmp/backup:/backup ubuntu tar cvf /backup/shiyanloudb.tar /shiyanloudata
ps: 宿主机的挂在目录会覆盖容器目录内容, 所以备份时容器中应该挂在一个新的目录
总结:
- 创建数据卷
- 管理数据卷权限
- 挂载宿主机文件
- 使用数据卷容器共享数据
- 数据卷备份
补充
挂载宿主机目录会导致容器内目录被覆盖,那么怎么做到互相映射呢?
当我们使用docker run -v /host/something:/container/something
尝试挂载默写目录到容器内时,期待的效果是容器内的文件和本地目录的文件相互映射,
但实际效果宿主机目录会直接覆盖掉容器内的目录,但容器内文件并非被删除,这个后面会讨论到。
容器内的文件被删除了吗?
答案是否定的, 容器的镜像自带的文件并没有被重写覆盖,而是被隐藏了, 原理类似于linux mount
的挂载,所以与其说是覆盖,不如说是目录挂载会掩盖。
解决方法
使用docker volume create
创建,这种方法创建的是数据卷
,而通过在创建容器时将主机本地任意路径挂载到容器作为数据卷的方式称为绑定数据卷
。
当我们需要将容器内文件映射,或者说是同步至宿主机的的文件夹里的时候,就可以通过数据卷的方式,具体指令如下:
docker run -it --name somename -v volume-name:/container-src anyimage /bin/bash #数据卷的两种方式 具名挂载: 指的是volume-name,主要不要添加`/`路径符。 添加路径符则表示使用的是上文中绑定数据卷的方式, 使用绑定数据卷是, 宿主机路径必须是绝对路径. 匿名挂载: 指的是-v 后面只有/container-src,这样容器目标路径会挂载在随机名的volume上.
查看
# 查看具体的volumen列表
docker volume ls
借鉴docker 的文档: https://www.yuque.com/leifengyang/oncloud/ox16bw