一.简介
-
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的linux或windows机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何接口.
-
Docker支持将软件编译成一个镜像,然后配置好镜像中的各个软件,将镜像发布出去,其他使用者可以直接使用这个镜像,运行中的这个镜像称为容器,容器启动是非常快速的.
核心概念
- docker主机(Host) : 安装了docker程序的机器(docker程序直接安装在操作系统上),一个物理或者虚拟的机器用来运行docker守护进程和容器
- docker客户端(client) : 连接docker主机进行操作
- docker仓库(registry) : 用来保存各种打包好的软件镜像
- docker镜像(images) : 软件打包好的镜像,存放在docker仓库中
- docker容器(container) : 镜像启动后的实例称为一个容器,容器是运行的一个或一组应用
一. 安装和配置
一键脚本安装
- 官方:
curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
- 国内:
curl -sSL https://get.daocloud.io/docker | sh
手动安装
-
Ubuntu下安装
-
设置仓库
- 卸载旧版本
apt-get remove docker docker-engine docker.io containerd runc
- 更新一下apt索引包
apt-get update
- 安装依赖
apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
- 添加docker官方GPG密钥
curl -fsSL https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
- 显示OK大概率就已经添加成功了,我们也可以用官方提供的指纹进行验证 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
apt-key fingerprint 0EBFCD88
搜索指纹后8位即可 - 设置使用稳定版仓库
add-apt-repository "deb [arch=amd64] https://mirrors.ustc.edu.cn/docker-ce/linux/ubuntu/ $(lsb_release -cs) stable"
- 卸载旧版本
-
安装Docker Engine-Community
- 更新apt索引包
apt-get update
- 安装最新Docker Engine-Community
apt-get install docker-ce docker-ce-cli containerd.io
如果想安装指定版本,则跳到下一步 - 列出仓库中可用的版本
apt-cache madison docker-ce
然后使用版本字符串(第二列)安装指定版本apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io
- 更新apt索引包
-
-
CentOS下安装
-
设置仓库
- 卸载旧版本
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
- 设置官方源地址稳定仓库
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
或者使用一些国内源地址- 阿里云
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 清华大学源
https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
- 阿里云
- 卸载旧版本
-
安装Docker Engine-Community
-
更新yum索引包
yum update
-
安装最新Docker Engine-Community
yum install docker-ce docker-ce-cli containerd.io
如果想安装指定版本,则跳到下一步 -
列出仓库中可用的版本
yum list docker-ce --showduplicates | sort -r
,然后使用版本字符串(第二列)安装指定版本yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
注意此处和ubuntu有一点区别版本号是用-
连接在后面,版本号的取值也有说法,例如
版本字符串即从第一个冒号(:)一直到第一个中杠(-) 并且用中杠连接软件包名和版本字符串
-
-
使用systemctl命令启动 systemctl start docker
更换docker镜像源
-
修改daemon.json文件
vi /etc/docker/daemon.json
如果daemon文件不存在,则执行创建-
{ "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn"] }
-
国内常用镜像源地址
- 中国官方
https://registry.docker-cn.com
- 网易
http://hub-mirror.c.163.com
- 中科大
https://docker.mirrors.ustc.edu.cn
- 阿里云
https://{your_id}.mirror.aliyuncs.com
- daocloud
http://{your_id}.m.daocloud.io
- 中国官方
-
-
重新加载daemon文件并重启docker
systemctl daemon-reload
systemctl restart docker
二. 常用命令
- 最常用
#创建容器并启动
#--name 容器名 指定容器名称
#-d 容器后台运行
#-p hostPort:containerProt 端口映射 前面是宿主机的端口,后面是容器的端口
#-e key=value 用来指定容器的启动参数,如果mysql的MYSQL_ROOT_PASSWORD
#--network=xxx或者--network xxx 用来指定容器的网络
#--network-alias xxx 用来指定容器在网络中的别名
#-v hostPath:containerPath[:ro] 挂载宿主机的目录到容器中,前面的宿主机目录路径,后面是容器内的目录路径,
# 两个路径都必须是绝对路径,默认挂载的权限为读写,如果指定为只读可用ro
#--privileged true/false(默认) 解决容器权限不足的问题 true为开启权限,默认false
docker run imageName:tag
#仅创建容器
docker create
#停止运行一个或多个容器
docker stop containerName
#启动一个或多个容器
docker start containerName
#设置docker服务开机自启(同下命令搭配使用)
systemctl enable docker
#设置容器开机自启(同上命令搭配使用)
docker update --restart=always containerName
#重启一个或多个容器
docker restart containerName
#重命名容器
docker rename oldName newName
#查看所有正在运行的容器 -a表示查看所有(包括没有在运行的容器)
docker ps [-a]
#查看所有镜像
docker images
#搜索镜像
docker search xxx
#拉取镜像
docker pull xxx:xx
#删除镜像
docker rmi imageName
#删除容器
docker rm containerName
#在docker容器中执行命令 -i 可输入 -t创建一个伪终端 -d后台模式 -u指定用户 如-u root
#常用 进入容器(就是执行容器内的/bin/bash文件,所以有些镜像可能没有/bin/bash,则需要根据镜像的介绍使用,但是大部分都是/bin/bash)
docker exec -it containerName /bin/bash
#也可使用另一个命令进入容器,但是一下方式有要给缺点,就是进入之后,在容器内使用exit命令,就会停止容器
docker attach containerName
#从容器内拷贝文件或目录到宿主机 不管容器是否启动,拷贝都是可以生效的
docker cp 容器名:容器内文件路径 目标路径(宿主机文件夹路径)
#拷贝文件或目录到容器内
docker cp 宿主机文件路径 容器名:容器内文件夹路径
#将容器制作为镜像,还能添加一些参数如
#-a 提交镜像的作者
#-c 使用dockerfile指令来创建镜像
#-m 提交时的说明文字
#-p 在commit时将容器暂停
docker commit -a "climbxu" -m "添加3306端口映射" mysql57 mysql:v1
- 查看信息相关
#查看容器详情
docker inspect containerName
#查看容器日志
docker logs containerName
#查看网络信息
docker network inspect networkName
#查看容器的所有进程
docker top containerName
#实时显示一个容器的资源占用
docker stats containerName
- 清理相关
#删除停止运行的容器
docker container prune
#删除所有容器(包括停止的,正在运行的) 慎用
docker rm -f $(docker ps -aq)
#列出所有数据卷
docker volume ls
#删除不再使用的数据卷
docker volume rm prune
#删除指定id的数据卷
docker volume rm containerID
#删除构建缓存
docker builder prune
#列出docker的磁盘使用情况
#images 所有镜像占用的空间,包括拉下来的和本地构建的
#containers 运行的容器占用的空间
#local volumes 容器挂载本地数据卷的空间
#build cache 镜像构建过程中产生的缓存空间
docker system df
#一键清理,删除关闭的容器,无用的数据卷和网络,以及无tag的镜像
docker system prune
#一键清理,更加彻底,可以将没有使用的镜像都删除掉
docker system prune -a
三. Docker的4种网络模式
Docker网络模式 | 配置 | 说明 |
---|---|---|
bridge模式 | -net=bridge | 每一个容器创建一个网络空间并与主机进行桥接,默认模式 |
host模式 | -net=host | 容器和宿主共享网络空间 |
container模式 | -net=container:NAME/ID | 多个容器共享网络空间 |
none模式 | -net=none | 容器有独立的网络空间,但并没有对其进行任何网络设置 |
bridge模式(默认)
-
类似于VMware中的桥接模式,在Docker启动的时候主机会新建一个虚拟网桥名为docker0,并将主机设置网关,此后,每有一个使用bridge的容器启动的时候,就会在主机创建一个名为vethxxx的虚拟网卡,而在容器中创建一个名为eth0的网卡,然后主机会将每一个vethxxx网卡桥接到docker0中
-
即每有一个使用bridge的容器启动时,都会到docker0中分配一个二级网络的ip,之后各容器之间,容器与主机之间都可以使用这个二级网络的ip进行互通,由于是桥接,容器也能访问外网
-
一下是使用birdge模式建立的两个容器
host模式
-
容器并不会创建新的网络,而是直接使用主机的网络,可以说这个模式下,容器的网络是没有隔离的,在容器中使用ifconfig和在主机中使用ifconfig看到的内容将是一样的
-
所以这个模式中也不能使用-p映射端口,因为容器使用的就是主机的网络,即使使用-p映射端口也是没有意义的,系统也会给出提示
-
由于所有host模式的容器都使用的是主机的网络,所以所有host模式的容器的端口不能重复,否则会提示占用
-
这个模式其实就是不隔离网络即ip和端口,但是其他方面还是隔离的,比如进程列表,文件系统还是和主机隔离的
container模式
-
即在创建容器的时候,指定一个已经存在的容器,共享他的网络(注意,不是共享主机的网络,而是共享指定容器的网络,当然,如果指定的这个容器使用的是host模式,那就是共享主机的网络)
-
也和host一样和指定的容器之间,只是不隔离网络,而进程列表,文件系统还是隔离的,和host模式唯一的区别就是,host模式是容器和主机之间共享网络,而container模式是容器与容器间共享网络
none模式
- 容器有自己独立网络空间,当没有进行任何配置,所以也没有网卡,只有lo本地回环,所以容器与容器不能互通,容器和主机也不能互通,容器也访问不了外网,也不能使用-p映射端口,因为没有Ip
- 此模式容器的网络空间完全封闭,较为安全
网络模式的选择
-
docker在安装之后自带了3个网络,我们可以通过
docker network ls
查看,默认的名字就是bridge(默认就是dokcer0),host,none,而我们使用–net=xxx或者默认不填的时候其实是加入默认的网络中,而我们也可以基于这3种网络模式定义自己的网络
-
首先,host模式和container模式的局限性较大(共享网络意味着端口不能重复),none模式没有进行任何网络配置,不能访问外网,不能和其他容器互通
-
所以我们最常用的还是bredge模式.但是,我们如果是用的是默认的(docker自带的bridge模式),那么又有问题,因为默认的bridge模式,容器与容器之间只能通过二级网络的ip来通信.但你非要使用默认的bridge模式,也不是没有办法,那就是通过–link来解决(不推荐),示例
docker run --name container1 -d imageName docker run --name container2 -d --link container1:c1 -d imageName #通过--link参数来连接,后面接已经存在的容器名:别名,此时container2可以通过ip,容器名,别名来访问container1,但是,反过来则不行,container1只能通过ip访问container2,因为--link的原理其实就是在container2的host文件中添加了映射,而container1已经创建,没有添加映射,所以不能
-
不推荐使用–link的方式,而是使用自定义网络的方式,而docker官方也推荐我们使用自定义网络
#步骤一 创建自己的bridge网络 docker network create myBridge #步骤二 创建容器,并加入到myBridge网络,并指定当前容器在网络中的别名,此后,我们所有容器能通过虚拟ip,容器名,别名等方式互通 docker run --name container1 --network myBridge --network-alias c1 -d imageName docker run --name container2 --network myBridge --network-alias c2 -d imageName
-
bridge模式每次重启容器后,容器的ip可能会发生改变,这也是不推荐使用–link的原因之一,但是我们想要固定容器的ip,在启动的时候也可以使用-ip参数指定
docker run --name container3 --net bridge --ip 172.17.0.2 imageName
-
–net是–network的简写,后面可以用空格,也可用=
-
一个容器也可以加入多个网络,但是启动的时候只能指定一个,启动之后可以进行修改(具体步骤到四.常见问题 参照)
四. 常见问题
对已经启动的容器进行修改(端口映射,文件挂载,网络配置等等)
-
解决方案1: 删除容器,重新创建
-
解决方案2: 把当前已经启动的容器构建为镜像,然后再根据这个镜像重新创建容器
#将容器制作为镜像,还能添加一些参数如 #-a 提交镜像的作者 #-c 使用dockerfile指令来创建镜像 #-m 提交时的说明文字 #-p 在commit时将容器暂停 docker commit -a "climbxu" -m "添加3306端口映射" mysql57 mysql:v1
-
解决方案3: 停掉docker服务,修改容器配置文件,重启docker服务(如果不熟练,慎用,修改之前记得保存容器,另外,此操作要关闭docker服务,所以修改配置文件一定要快,不然有人会提刀过来找你)
修改端口映射
修改之前先停掉docker服务(一定要停掉,不然重启之后又会改回来),停止docker之后可能会提示docker.socket还在运行,所以我们再把docker.socket也停止一下
找到对应容器的配置文件 /var/lib/docker/containers/容器的id(前12位相同)/hostconfig.json,可能是没有格式化的,可以全部复制出来,改完再放回去
找到PortBindings,在这里添加端口映射,我这里容器是没有任何端口映射的,如果容器有端口映射,我们可以直接复制一份作修改即可
此处我添加了一个3306的端口映射,注意,外面的是容器的端口,里面的是宿主机端口
然后修改config.v2.json,这个文件有两处需要修改
这里第一处ExposedPorts意味暴露端口,此镜像默认就暴露了3306和33060端口,但是我们没有进行映射
这里我们宿主机的3307端口映射到容器的3306端口,由于此镜像默认暴露了3306端口,所以第一处无需修改,另外第二处配置了两个映射,0.0.0.0是ipv4,::是ipv6,没有需求的话ipv6可以不配置
修改文件挂载
和修改端口映射一样,还是先停掉docker服务,找到配置文件
我们将宿主机的/var/lib/docker/mydir挂载到了容器的mydir
接着我们修改config.v2.json文件,首先找到MountPoints这个节点,然后在下面添加挂载
这里我们添加一个了一个挂载信息,我门可以参照它原来有的一个,但是要注意,不一样,上面一个是数据卷,而我们是挂载
修改网络
#一个容器加入多个网络,但是在启动的时候只能指定一个,启动之后我们可以让其加入其他网络
#让容器连接到网络
#--alias 容器在网络中的别名
#--ip 指定容器在网络中的ip
#--ipv6 指定容器在网络中的ipv6地址
docker network connect --alias=c1 networkName containerName
#让容器link到另一个容器 修改的是containerName2的hosts
docker network connect containerName1 containerName2
#容器与网络断开连接
docker network disconnect networkName containerName
容器权限不足问题
-
解决方案一: 在容器启动的时候添加参数
Privileged=true
,如果容器已经启动,则可以把当前容器构建成镜像再启动,或者直接修改hostconfig.json文件(需要先把docker服务停掉) -
解决方案二(主要是使用docker exec执行命令或者进入容器内的操作权限不足等问题): 可以在docker exec后面加入参数
-u root
使用root用户
启动报WARNING: IPv4 forwarding is disabled. Networking will not work.
- 原因是主机存在多个网卡,是否进行转发,只需改动
/etc/sysctl.conf
配置文件net.ipv4.ip_forward=1
表示开启转发 - 还有一些情况也可以考虑是否开启了这个转发,比如容器已经配置好端口映射并且启动了,用netstat命令也能看到端口正在使用,但是在外面就是连接不了