Docker笔记
docker就是一个容器,可以理解为更进一步的虚拟机。
文章目录
Docker初级篇
1. docker是什么
-
docker就是一个容器,可以理解为更进一步的虚拟机。
-
理念:Build, Ship and Run Any App, Anywhere.
-
网址
-
官网:https://docker.com/
-
仓库:https://hub.docker.com/
-
-
基本架构
Docker 采用了
C/S
架构,包括客户端和服务端。Docker 守护进程 (Daemon
)作为服务端接受来自客户端的请求,并处理这些请求(创建、运行、分发容器)。客户端和服务端既可以运行在一个机器上,也可通过
socket
或者RESTful API
来进行通信。
2. docker思想
-
docker就是一头载着许多集装箱的鲸鱼
-
一次镜像,到处运行。
-
隔离性:容器之间相互独立,互不相通。
-
容器就是进程。
-
开发+运维 = Devops,开发运维一体化。
-
Docker实质上就是在现有系统内制造了一个隔离的文件环境,它的执行效率几乎等同于宿主机。
-
docker为什么这么快**?**
因为它是一个极小型的Linux系统,只加载需要的文件,而且容器内的应用直接运行在宿主机的内核上,容器没有自己的内核、也未虚拟我们的硬件系统。
-
Docker三件套
- 镜像 image:一个镜像可以创建多个容器。
- 容器 container:创建一个最小化的Linux环境,需要的就加载、不需要的就不加载。
- 仓库 repository:存放各种镜像。
-
镜像是分层的,里面是UnionFS联合文件系统。
-
镜像层 与 容器层
- 镜像层为只读,不可修改
- 容器层在镜像层之上,可以读写。
<img src="/Users/thinkstu/Library/Application Support/typora-user-images/image-20220324193021492.png" alt="image-20220324193021492" style="zoom: 33%;" />
- 默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器
3. 安装
安装方式:1. 官方 2. 我的安装
前提条件:原先未安装Docker
- 卸载旧版本
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
- 官方安装
我采用了yum的阿里源(并非第5条提到的docker阿里源),官方的慢。
#安装gcc
yum -y install gcc
yum -y install gcc-c++
# 安装 yum-utils 包,并设置稳定存储库,目的:提供安装docker的库
yum install -y yum-utils
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#正式安装docker
yum install docker-ce docker-ce-cli containerd.io
- 我的安装
更胜一筹?学了这么久,我竟然现在才知道踩了一个大坑。yum list中排名第一docker版本是2017年的1.13.1版本。而最新的是2022年的20.10.14版本,我一直用着2017年版的,怪不得好多命令都没有!
#错误的做法,2017版本:yum -y install docker
#正确的做法:安装最新版,ce社区版本
yum -y install docker-ce.x86_64
- 配置docker
systemctl start docker
systemctl enable docker
- 测试(可省略)
docker run hello-world
-
docker配置阿里云加速
-
说明:每位开发者一个账号
-
登录阿里云 — 控制台 — 容器服务 — 容器镜像服务 — 地址
-
服务器配置
sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://xx2ypep6.mirror.aliyuncs.com"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker
-
4. 镜像
- 概念:
- 类型:模板
- 要求:镜像名强制小写
- 显示镜像
docker images
#或
docker image ls
镜像名 标签(版本) 镜像id(主键) 创建日期 大小
- 搜索镜像
docker search xxx
docker search --limit 5 xxx #limit默认是25条,不过这里我更愿意用head
---------
docker search xxx |head -6 #但注意:上面这里包括了一行头标题,故-6
- 拉取镜像
docker pull 镜像文件名 #默认最新版
docker pull centos #latest
docker pull centos:7.9.2009
镜像版本信息请到官网查看
- 删除镜像
docker rmi -f xxx
docker rmi -f $(docker images -qa) #递归删除全部镜像
4. 镜像进阶
-
docker tag指令
docker tag指令标记本地镜像,将其归入某一仓库。
[root@vm-4-3-centos ~]$ docker tag --help Usage: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG] Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
- 其指令是针对镜像,而commit、export是针对容器,完全不一样。
- 作用:推送至远程仓库时需要tag给镜像备注。
- docker tag只起标记作用,相当于给镜像重命名、制作硬链接。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rN3LTluK-1651739265985)(https://tva1.sinaimg.cn/large/e6c9d24egy1h0xfv6e7o4j213g04gmy5.jpg)]
5. 容器
容器只要创建了就会存在,即使退出关闭后也可以再次重启。
可使用
docker system df
查看现容器情况
- run容器
docker run -it -p 80:8080 --name="myUbuntu" ubuntu bash
参数说明
-p 8080:80 #小p,指定端口映射:宿主机端口:容器内端口
-P #大P,系统随机分配端口,Publish all exposed ports to random ports
-d #后台运行
-i #interaction,交互模式
-t #tty,为容器重新分配一个伪输入终端
-it #常组合使用
--name #指定容器名称
--privileged=true #赋予容器root权限,默认不赋予
-
退出容器
-
ctrl + p + q :终端后台挂起
-
exit:终端销毁(销毁单终端容器,容器暂停)
-
-
再次进入容器
- exec:新建终端并进入
- attach:返回后台终端
-
rm 删除容器
docker rm -f xxx #或者 docker stop xxx docker rm xxx
删除所有容器
docker rm -f $(docker ps -aq)
-
ps指令
-
说明:单纯的ps指令只能查看当前活着的进程(并非所有)。
-
使用:
docker ps -a #所有,all -l #最近,latest -n 5 #指定数量,number -q #静默模式,queue 只显示容器编号
-
-
启动、重启、停止、强制停止容器
容器要处于开启状态才能使用
docker start xxx docker restart xxx docker stop xxx #停止 docker kill xxx #强制停止
-
清除所有处于终止状态的容器
$ docker container prune
-
容器的名称是唯一的,不可重复。
5. 容器进阶
-
容器自动退出机制
-
Docker容器后台运行,就必须有一个前台进程。容器运行的命令如果不是那些一直挂起的命令(比如运行top,tail),就会自动退出。
-
例子
run -d ubuntu之后却发现后台没有存在ubuntu进程 —> 无事可做,已被关闭。
但是像Mysql、Redis之类的就不会被关闭,因为 —> 还有事可做。
-
解决方案:
针对Docker中存在着这个机制的问题,我们就只能按照以下三步走。
- 前台启动进程 -it
- Ctrl+p+q退出
- docker ps观察是否成功
-
-
logs打印容器日志
docker logs -ft xxx -f # 流输出,即持续输出/类似于Linux下的tail -t # 顺带输出时间戳 -n # 指定开始输出的行数,-f可破坏此规则
-
top查看容器内运行的进程
docker top xxx
有点长
-
inspect显示容器具体信息
**结论:**当容器中的所有终端都被关闭时,容器停止运行。(节省资源)
- 返回一JSON格式信息
docker inspect xxx
docker exec xxx bash #exit退出时,容器自动回归后台
-
diff查看容器内部文件系统变化
**作用:**查看容器内部文件系统的改动记录
**说明:**A - Add, D - Delete, C - Change
但是根据我的观测可能不是特别的准确,比如我在根目录下新增了一文件夹a,这里竟然显示D。然后我又在/a里新建文件夹,显示为A,正常。
[root@VM-4-3-centos ~]# docker diff --help Usage: docker diff CONTAINER
[root@VM-4-3-centos ~]# docker diff 3fe998f421b4 D /a C /run D /run/secrets C /var/lib/systemd A /var/lib/systemd/a.txt D /var/lib/systemd/random-seed
-
stats:查看容器占用内存
docker stats 27dfdb752738
-
docker cp文件复制
作用:将容器内的文件复制到(备份到)宿主的计算机。
公式:
docker cp 容器id:容器内路径 宿主路径
实操
docker cp 095333dc1a5a:/test/a.txt .
-
commit成新镜像
慎用commit:https://yeasy.gitbook.io/docker_practice/image/commit
用作备份还好,当用作制作新镜像就有点糟糕。
-
思想:将当前容器提交成为新的镜像,产生新的镜像文件(不会覆盖原来的)。
-
代码:
#--author 是指定修改的作者,而 --message 则是记录本次修改的内容。 docker commit -m="" -a="" 容器id 包名/镜像名:版本号 docker commit -a="thinkstu" -m="enhance version for vim" \ 4ccdf283ef3c thinkstu/ubuntu_vim:1.0.1
-
-
容器完整备份
思想:直接将容器打包成一个tar包,需要的时候再导进。
-
两种命令
- 导入:import
- 导出:export
-
export公式
docker export xxx > 导出文件名.tar docker export 095333dc1a5a > ubuntu222.tar
-
import公式
cat 文件名.tar | docker import - 组织名/镜像名:版本号 cat ubuntu222.tar |docker import - thinkstu/ubuntu_test:1.0.1
- 注意事项:
- 当我们将一个容器完整容器export导出时,它是作为一份镜像被导出。
- 所以当我们import导入一个tar包的时候,我们需要手动的填入一些信息,包名、镜像名、版本号,导入的文件也是一个镜像,而不是容器.
- 注意事项:
-
commit与export的理解
commit是在本地直接将容器打包成镜像的操作,属于提交的类型。
export指令则先将容器commit成一个新镜像,然后再使用tar将镜像打包导出到宿主机。
6. 仓库
三种仓库:阿里云、私有云、官方
**推荐:**阿里云(默认私有)、私有云(默认公开)
**不推荐:**官方(默认公开、访问速度慢)
1. 阿里云
阿里云Docker镜像仓库( 个人免费+企业收费 )
阿里云仓库默认私有,只有登录才能下载
可以更改为公共的,让其他人不需要登录就能下载
-
创建阿里云容器镜像服务、个人实例。
-
创建命名空间
-
以命名空间为基础创建仓库
-
推送至远程仓库
#登录、按要求打包、提交至远程仓库
docker login --username=tb174293514 registry.cn-beijing.aliyuncs.com
docker tag [ImageId] [阿里云地址]/[命名空间]/[镜像重命名]:[镜像版本号]
docker push registry.cn-beijing.aliyuncs.com/thinkstu/uu:1.0
实例
#三段式:登录、打包、上传
docker login --username=tb174293514 \registry.cn-beijing.aliyuncs.com
docker tag 9b495bdf4db2 registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:1.0.1
docker push registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:1.0.1
拉取远程仓库的内容:到阿里云仓库中亲自查询再pull方便些
#两段式:登录、拉取
docker login --username=tb174293514 registry.cn-beijing.aliyuncs.com
docker pull registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:[镜像版本号]
2. 私有云
私有云自搭建之初就是公有的,任何人都可以拉取的到
所以我只要将拉取的链接直接发给别人就好
不过对方主机要先放开对我服务器域名的安全限制,具体做法与下面本机修改安全协议一样
-
具体思路:利用Dockerz自建仓库( registry ),然后开放端口、配置信息。
-
搭建私有云服务器
-
拉取镜像registry
-
运行容器、端口映射
-
访问测试(宿主机外网、宿主机内网、docker内网)
docker pull registry docker run -d -p 5000:5000 \ -v ~/myregistry/:/tmp/registry \ --privileged=true registry curl -XGET http://42.192.83.9:5000/v2/_catalog curl -XGET 10.0.4.3:5000/v2/_catalog curl -XGET 172.17.0.1:5000/v2/_catalog #测试结果:空空如也 {"repositories":[ ]}
-
-
上传镜像至私有云
-
修改安全协议
-
commit提交容器为新镜像
-
tag 修改镜像格式
-
上传push
提示:如果在第一步就把镜像名规范化,则第二步可以不需要。
Docker默认不支持http协议,修改配置使push跳过安全机制
vim /etc/docker/daemon.json #新增一行,记得在上行加逗号 , "insecure-registries": ["172.17.0.1:5000"] #重启docker服务,使服务生效 systemctl restart docker
docker commit -m="enhance ubuntu for ifconfig" -a="thinkstu" c4ca8d49a98f myubuntu_ip:1.0.2 #相对于阿里云,这里的命名空间不是必须的 docker tag [image_id] [私有云地址]/[命名空间]/[镜像重命名]:[镜像版本号] docker tag myubuntu_ip:1.0.2 172.17.0.1:5000/myubuntu_ip:1.0.2 docker push 172.17.0.1:5000/mybuntu:1.0.2 #查看是否上传成功 curl -XGET 172.17.0.1:5000/v2/_catalog {"repositories": [ "mycentos", "thinkstu/mycentos", "thinkstu/mycentos02"]}
-
-
pull从私有云拉取镜像
#查看私有云上的软件信息与版本号 #1. 查看私有云镜像列表 curl 172.17.0.1:5000/v2/_catalog #2. 根据镜像名寻找版本 curl 172.17.0.1:5000/v2/[镜像全名]/tags/list curl 172.17.0.1:5000/v2/thinkstu/mycentos/tags/list {"name": "thinkstu/mycentos", "tags": [ "1.2", "1.1"]} docker pull 172.17.0.1:5000/mycentos:1.2
3. 官方仓库
上传至官方仓库的镜像默认公开
免费版本只能对设置一个镜像为私有
-
官方网站注册账号
-
登录账号
-
提交镜像
docker login -u thinkstu
#1.'tag镜像':[地址]/[命名空间]/[镜像重命名]:[镜像版本号] docker tag centos04:1.0 thinkstu/centos:9.9 #2. '提交镜像' docker push push thinkstu/centos:9.9
这里
- 地址可以没有,默认:docker.io/
- 命名空间必须是 docker网站的用户名
-
拉取镜像
用户名(命名空间)/镜像名 : 版本号
push thinkstu/centos:9.9 #速度也非常的慢
4. 三种方式对比
都源自在官方提供的接口上进行定制化
- 登录:阿里云与官方只有登录之后才能进行push操作,否则会提示未授权。
'用法:docker login [OPTIONS] [SERVER]
'阿里云'docker login -u=tb174293514 registry.cn-beijing.aliyuncs.com
'私有云'无需登录
'官方 'docker login -u thinkstu
- tag:[云地址]/[命名空间]/[镜像重命名]:[镜像版本号],标记镜像、为push做准备。
docker tag 9b495bdf4db2 \
registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu:1.0.1
docker tag 39272891e4b4 \
172.17.0.1:5000/myubuntu_ip:1.0.2
docker tag centos04:1.0 \
thinkstu/centos:9.9
3. **push**
前提:已登录。
push目标其实由两个因素构成:云地址+命名空间
云地址为产商标识、命名空间可看作用户标识(用户名)
'阿里云'docker push registry.cn-beijing.aliyuncs.com/thinkstu/ubuntu_vim:1.0.1
'私有云'docker push 172.17.0.1:5000/mybuntu:1.0.2
'官方 'docker push thinkstu/centos:9.9
'相当 'docker push docker.io/thinkstu/centos:9.9
-
pull公有仓库
直接登录事先存在的仓库地址查看版本信息,然后直接pull。
7. 网络
docker中所有的网络都是虚拟的,转发效率高(内网传递)。
当创建容器时如没有指定网段,则会被分配到默认网段docker0。
默认情况下,容器可以主动访问到外部网络的连接,但是外部网络无法访问到容器。
-
原理:veth-pair技术
veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着。正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备
每次创建一个新容器的时候,Docker 从可用的地址段中选择一个空闲的 IP 地址分配给容器的 eth0 端口。使用本地主机上
docker0
接口的 IP 作为所有容器的默认网关。https://www.cnblogs.com/bakari/p/10613710.html
-
宿主机上查看ip信息
三个地址:
- lo:loop,服务器回环地址 127.0.0.1
- eth0:Ethern 0,以太网第一个网卡接口,腾讯云内网地址10.0.4.3
- docker0:docker的第一个网卡接口,地址172.17.0.1,为虚拟的路由器,负责转发容器内的网络请求
-
容器内查看ip信息
yum -y install iproute
两个地址:
- 容器回环地址
- eth0@if9:172.17.0.2
-
docker网络小结:
- docker使用的是Linux的桥接
- 宿主机是一个Docker容器的网桥docker0。
-
–link参数说明
已淘汰,不推荐;
为什么需要它?
想让容器之间通过容器名相互ping通,而不是通过内网ip地址;从而解决docker重启后网络地址随机分配的尴尬。
# 现在 tomcat03可以直接在内部ping通tomcat02,但是反过来不行 docker run -d -P --name tomcat03 --link tomcat02 tomcat
- 原理:–link指令在run创建这个容器的时候改写了容器内部的
/etc/hosts
字段,本质就是改写了映射规则,所以03能直接通过名称找到02。 - **小技巧:**直接查看/etc/hosts文件能看到此容器中的所有映射关系。
- 原理:–link指令在run创建这个容器的时候改写了容器内部的
-
查看docker内部所有的网络配置
[root@vm-4-3-centos ~]$ docker network --help Usage: docker network COMMAND Commands: connect Connect a container to a network ' create Create a network disconnect Disconnect a container from a network inspect Display detailed information on one or more networks ' ls List networks prune Remove all unused networks rm Remove one or more networks
[root@vm-4-3-centos ~]$ docker network ls NETWORK ID NAME DRIVER SCOPE df364ea5e865 bridge bridge local 5ef346efe85f host host local 6b307841d021 none null local #备注:这里有两列bridge,其中有一列是name名字,另一列是driver驱动类型。 # 并不一样,这一查看方法 [root@vm-4-3-centos ~]$ docker network inspect df364ea5e865 #返回JSON字符串
-
自定义网络(容器互联)
取代–link
网络配置分类 :
- bridge:桥接 (默认,自己创建也是用的bridge模式)
- none:不配置网络,一般不用
- host:和主机共享网络
- container:容器网络连通(少用,局限性很大)
自定义网络优势:
docker为我们自定义的网络维护好了对应的关系,会比docker0更优。
实现思路:
利用docker network create指令创建属于自己的网络,在后续创建容器时指定容器使用该网络。
开始自定义网络:
[root@vm-4-3-centos ~]$ docker network create --help #只列出3参数,其实还有其他的许多 Usage: docker network create [OPTIONS] NETWORK Options: -d --driver Driver to manage the Network --gateway IPv4 or IPv6 Gateway for the master subnet --subnet Subnet in CIDR format that represents a network segment
'范例,其中:子网掩码和网关必须配置,--driver默认就是bridge、故可不写。 docker network create -d bridge --gateway 192.168.0.1 --subnet 192.168.0.0/16 mynet
-
查看我们自定义的网络配置:
-
使用我们自定义的网络配置
docker run -it --name centos-net-01 --net mynet docker.io/centos:7.9.2009
-
查看刚运行起来的centos容器配置
docker inspect fc2575aa6ea5
- 网络互联
- 解决问题:网络段之间的互联问题,现在tomcat01与tomcat02因为处于不同的网段,所以它两暂时不能ping通。
[root@07741f074e88 /]$ ping 192.168.0.2 PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. ^C --- 192.168.0.2 ping statistics --- 13 packets transmitted, 0 received, 100% packet loss, time 12000ms # 100% 的丢包率
-
解决思路:我们为 tomcat02 再赋予192.168.0.1段的地址即可。
-
解释:相当于tomcat02拥有两块网卡,这两个网络段全部把它接入(当然这是虚拟的)。
-
实现:docker network connect
connect将一个网段赋于容器中
[root@vm-4-3-centos ~]$ docker network connect --help Usage: docker network connect [OPTIONS] NETWORK CONTAINER 'Connect a container to a network Options: --alias Add network-scoped alias for the container --help Print usage --ip string IP Address --ip6 string IPv6 Address --link list Add link to another container (default []) --link-local-ip Add a link-local address for the container
#不需要参数,直接链接 docker network connect mynet test1 #查看mynet网段中的信息 docker network ls docker network inspect 6afc49097296 #尝试一下现在能否ping成功:成功! [root@07741f074e88 /]$ ping 192.168.0.2 PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. 64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.093 ms 64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.071 ms ^C --- 192.168.0.2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.069/0.077/0.093/0.014 ms
- 指定容器ip地址==–ip==
前提:跟所在网络的配置相符
docker run -it --name centos-net-01 --net mynet --ip 192.168.22.03 docker.io/centos:7.9.2009
-
docker网络参数说明
-
--net=bridge
这个是默认值,连接到默认的网桥。 -
–net=host告诉 Docker 不要将容器网络放到隔离的命名空间中,即不要容器化容器内的网络。此时容器使用本地主机的网络,它拥有完全的本地主机接口访问权限。容器进程可以跟主机其它 root 进程一样可以打开低范围的端口,可以访问本地网络服务比如 D-bus,还可以让容器做一些影响整个主机系统的事情,比如重启主机。因此使用这个选项的时候要非常小心。如果进一步的使用
--privileged=true
,容器会被允许直接配置主机的网络堆栈。=host 容器直接与主机共享网络、端口;
-
--net=container:NAME_or_ID
让 Docker 将新建容器的进程放到一个已存在容器的网络栈中,新容器进程有自己的文件系统、进程列表和资源限制,但会和已存在的容器共享 IP 地址和端口等网络资源,两者进程可以直接通过lo
环回接口通信。 -
--net=none
让 Docker 将新容器放到隔离的网络栈中,但是不进行网络配置。之后,用户可以自己进行配置。
-
大写P的映射规则:当使用P(大写的)标记时, Docker 会随机映射一个 49000~49900 的端口
到内部容器开放的网络端口。(注意其的范围,任意也是有限制的)
8. 数据卷
-
数据卷是什么?Volumn,一种数据的备份、共享策略。
-
底层理解:硬链接。
-
在宿主机与容器中存在着一种现象:两个目录共享一份文件系统。其中,容器中的这个目录是独立于容器本身的UnionFS联合文件系统,所以即使删除该容器,存在于共享目录的文件还是会被保存下来,位于宿主机中。
-
作用:
- 数据备份:用作容器拷贝的利器。
- 共享文件:宿主机与容器之间、容器与容器之间,例如10个redis容器共享一份配置文件。
-
数据卷参数-v、–:
可挂载多个volumn
#目录如不存在则新建
docker run -it -v ~/myData:/etc/data -v ~/myBin:/bin \
--privileged=true centos
- 查看某容器的数据卷路径
docker inspect 容器id
- 具名挂载、匿名挂载
数据卷挂载的两种方式
#具名挂载,挂载的路径由用户自定义
docker run -d -v ~/mysql/data:/var/lib/mysql mysql
#匿名挂载:未指定宿主机的挂载地址,默认分配到/var/lib/docker/volumn目录
docker run -d -v /var/lib/mysql
- 具名挂载说明:实名挂载,指定双方相互挂载的路径。
- 匿名挂载说明:宿主机匿名、容器实名,在宿主机上随机生成匿名代号。
- 查看宿主机上匿名挂载的数据卷
cd /var/lib/docker/volumn
cd ......
cd _data
- 查看volumn指令帮助
[root@vm-4-3-centos ~]$ docker volume --help
Usage: docker volume COMMAND
Commands:
create Create a volume
inspect Display detailed information on one or more volumes
ls List volumes
prune Remove all unused volumes
rm Remove one or more volumes
- 数据卷挂载新需求:只读权限
在多容器共享数据卷时很有用。
-
容器内只能读,宿主机能读能写。
-
实现:rw:能读能写(默认值)、ro:read-only只能读
docker run -d -p 5000:5000 -v /thinkstu/myregistry/:/tmp/registry:ro \ --privileged=true registry
- –volumes-from:数据卷继承
便捷实现多个Docker容器之间、宿主机之间数据共享:直接继承即可。
docker run -it --name "myubuntu100" --volumes-from [容器id] \
--privileged=true ubuntu
9. 常用操作
- system df查看镜像与容器情况
docker system df
- 用完即删
docker run -it --rm tomcat
- 不进入容器执行指令
docker run -d centos ls -l
- 清除无主的数据卷、无用的镜像、暂停的容器
docker volume prune
docker image prune
docker container prune
#prune , Remove all stopped containers
- –restart参数说明
--restart = always | unless-stopped | no | on- failure
- 容器退出后自动删除
--rm=true | false #容器退出后是否自动删除,不能跟 同时使用
- 限制容器的内存使用量
-m, - -memory = 1g #单位可以是b/k/m/g
- run指令等于先执行create指令再执行start指令。
- docker -itd操作诠释
#可以让ubuntu这类的系统直接进入后台运行而不真正的退出
docker run -itd ubuntu
-
如果要删除一个数据卷,必须在删除最后一个还挂载着它的容器时显式使用
docker rm -v
指令来指定同时删除关联的容器。
8. 日常实践
1. 启用systemd服务
简介:删删删东西,然后build重构。
- 解决Docker中CentOS镜像无法使用systemd的问题
- https://developer.aliyun.com/article/688670
- #直接下载作者制作好的镜像:
# 下载镜像
docker pull 2233466866/centos-systemd
# 通过镜像运行一个名为test的容器
docker run -dit -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name=test --privileged=true 2233466866/centos-systemd
2. 查看系统自启动程序
systemctl list-unit-files
3. Docker安装宝塔
-
创建CentOS容器
docker run -it --restart=always --name baota \ -p 80:80 -p 443:443 -p 888:888 -p 8888:8888 \ --privileged=true -v /home/www:/www centos7.9.2009
-
参数说明
#容器开机自启 –restart=always #映射宝塔主要需要的端口,也可以自己添加如3306等端口 -p 80:80 -p 443:443 -p 888:888 -p 8888:8888 映射本地的/home/www作为容器的/www目录 -v /home/www:/www
-
centos内安装宝塔
yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh
-
关闭宝塔面板的离线模式(否则处于离线状态、无法访问)
rm -rf /www/server/panel/data/not_network.pl && bt reload
-
设置宝塔程序自启动注意:编写脚本——方式多样,实现的效果也多样。
4. ubuntu安装vim
-
Docker原生的ubuntu是精简版本,没有携带vim。
-
apt-get指令, 简写:apt。
-
安装
Docker 镜像在制作时为了精简清除了
apt
仓库信息,因此需要先执行apt-get update
命令来更新仓库信息。更新信息后即可成功通过apt-get
命令来安装软件。apt update #更新索引 apt -y install vim #安装vim
5.vi与vim
注意:centos与ubuntu中虽然无vim,但是有vi啊,也不是不能编辑!节省空间!
vi a.txt
6. Docker可视化
两种方案:portainer:初级,Rancher:企业。
# 在此,--restart=always总是自启动,除非被docker stop
docker run -d -p 8000:8000 -p 9443:9443 --name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:2.9.3
7. 正确启动容器的流程
docker start xxid
docker exec -it xxid /bin/bash
8. 授予容器root权限
问题:Docker挂载主机目录访问时出现cannot ope directory : Permission denied
docker run -it --privileged=true centos
9. 容器的宿主机目录
我们查看到docker的容器在宿主机上的存放地点
cd /var/lib/docker/containers/
10. 安装mysql
-
存在的问题:
- 5.7版本中文乱码
- 数据如何备份
.# mysql内部查看mysql现阶段字符集 show variables like 'character%'
-
解决方案
#1. 数据备份问题
'/var/lib/mysql: 数据
'var/log/mysql: 日志
'etc/mysql/conf.d: 配置
docker run -d -p 3305:3306 --privileged=true \
-v ~/mysql/log:/var/log/mysql \
-v ~/mysql/data:/var/lib/mysql \
-v ~/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 --name mysql_test mysql
'-e设置初始参数,这里:mysql初始密码。
#2. 5.7版本中文乱码问题
[root@VM-4-3-centos /]$ vim /thinkstu/mysql/conf/my.cnf
[client]
default_character_set=utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
#写入以上内容,重启mysql容器服务:docker restart xxx
- 后续情境:mysql容器被误删时如何恢复?
#再次新建 Mysql for Docker 容器,使用相同的数据卷映射
docker run -d -p 3306:3306 --privileged=true \
-v /thinkstu/mysql/log:/var/log/mysql \
-v /thinkstu/mysql/data:/var/lib/mysql \
-v /thinkstu/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
11. 运行SpringBoot程序
不依赖宝塔,轻量级运行
- 宿主机拿到jar包+编写Dockerfile(其中
FROM JDK8
)
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
- 将以上传至服务器,然后使用
docker build
构建成镜像、运行
docker build -t mySpringboot .
**注意:**不要傻乎乎的将构建成的镜像文件上传至公共仓库,这样会被别人盗取的!
12. 取消默认截断
docker中存在着对长字符串默认截断的参数,我们可以禁止它。
docker ps --no-trunc
Docker高级篇
Dockerfile
作用:构建镜像
解释:通过编写指令脚本来构建镜像,可以在镜像构建之初就并入部分操作。
1. 指令诠释
全部大写
FROM 'from 基础镜像'
MAINTAINER 'maintainer 镜像维护者:标签已被淘汰'
LABEL 'label 镜像标签:官方现在推荐使用此标签'
RUN 'run 镜像构建时需要运行的命令'
ADD 'add:添加镜像、压缩包等,提供自动解压功能
WORKDIR 'workdir 镜像默认的工作目录
VOLUMN 'volumn 挂载目录(数据卷)
EXPOSE 'expose 暴露端口
CMD 'command 指定容器启动时运行的指令,只有最后一个会生效
ENTERPOINT 'enterpoint 指定容器启动时运行的指令,可以追加
ONBUILD 'onbuild 以当前镜像为基础镜像,构建下一级镜像的时候触发
COPY 'copy 类似ADD,拷贝宿主机文件到镜像,需指定目录
ENV 'enviroment 设置构建时的环境变量(持续到容器时期)
2. 官方centos7
scratch:这个镜像是虚拟的概念,实际并不存在,它表示一个空白的镜像。
FROM scratch
ADD centos-7-x86_64-docker.tar.xz /
LABEL \
org.label-schema.schema-version="1.0" \
org.label-schema.name="CentOS Base Image" \
org.label-schema.vendor="CentOS" \
org.label-schema.license="GPLv2" \
org.label-schema.build-date="20201113" \
org.opencontainers.image.title="CentOS Base Image" \
org.opencontainers.image.vendor="CentOS" \
org.opencontainers.image.licenses="GPL-2.0-only" \
org.opencontainers.image.created="2020-11-13 00:00:00+00:00"
CMD ["/bin/bash"]
3. build 构建镜像
步骤:编写dockerfile脚本文件,build构建centos镜像。
vim dockerfile01
ROM centos:7.9.2009
LABEL\
com.thinkstu.name="THINKSTU"
ENV file /tmp
WORKDIR $file
RUN yum -y install vim
EXPOSE 8081
CMD /bin/bash
docker build -f dockerfile01 -t centos_02:1.0 .
'命令详解:
'-f 使用本地的dockerfile文件。
#如果dockerfile文件名就是dockerfile,则可以不需要此参数进行指定
'-t 指定名称
'最后英文句号"."告诉docker应该在当前目录中寻找dockerfile01文件
4. history指令
**介绍:**可以查看任意镜像的构建历史(即过程)
**作用:**为我们模仿编写dockerfile文件提供便利
docker history eeb6ee3f44bd
#输出结果倒序查看,或者利用cat的相反数:tac
docker history eeb6ee3f44bd | tac
5. 定制化感悟
-
Dockerfile 中每一个指令都会在镜像中建立一层,Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。不要让docker镜像拥有过多层级,使用==&&==削减层级。
糟糕的写法(五层):
FROM debian:stretch RUN apt-get update RUN apt-get install -y gcc libc6-dev make wget RUN mkdir -p /usr/src/redis RUN make -C /usr/src/redis RUN make -C /usr/src/redis install
正确的写法(一层):
FROM debian:stretch RUN set -x; buildDeps='gcc libc6-dev make wget' \ && apt-get update \ && mkdir -p /usr/src/redis && make -C /usr/src/redis \ && make -C /usr/src/redis install \
-
镜像是多层存储,每一层的东西并不会在下一层真正被删除,只是会被标记为已删除、一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该被及时手动清理掉,否则多层下来镜像臃肿不堪。
#比如最后执行yum清除缓存操作 yum clean all
-
关于build指令构建时的那个小点 " . "
当构建的时候,用户会指定构建镜像上下文的路径,
docker build
命令得知这个路径后,会将路径下的所有内容打包,然后上传给 Docker 引擎。这样 Docker 引擎收到这个上下文包后,展开就会获得构建镜像所需的一切文件。有些初学者在发现
COPY /opt/xxxx /app
不工作后,于是干脆将Dockerfile
放到了硬盘根目录去构建,结果发现docker build
执行后,在发送一个几十 GB 的东西,极为缓慢而且很容易构建失败。那是因为这种做法是在让docker build
打包整个硬盘,这显然是使用错误。原来如此,所以我们才需要在每一次构建时都新建一空白的目录!
-
Docker 不是虚拟机,容器中的应用都应该以前台执行,而不是像虚拟机、物理机里面那样,用
systemd
去启动后台服务,容器内没有后台服务的概念。对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。
错误范例:
#容器中根本就没有systemctl、service这样的概念(但是可以通过一些技巧得到,原此) systemctl start nginx service nginx start
正确的做法是直接执行
nginx
可执行文件,并且要求以前台形式运行。比如:"nginx -g daemon off
-
数据卷感悟
- 在容器中使用数据卷能够提高容器在运行时的读写效率。(此时数据将直接写入宿主机中而不是容器,减少了一层套壳)
- 另外,我在编写Dockerfile的时候就可以编写一些匿名的数据卷,这样就不用怕数据的丢失。而且如果我日后有指定数据卷,那么直接指定即可,匿名的将会失效。
- 容器内的数据在容器销毁的时候会丢失,但是数据中的不会。
compose
美好情境:一份yml文件,一键部署
-
解释性说明:
- 使用yaml文件定义服务
- 帮助定义和共享多容器应用程序
- **最大优点:**原先公司启动100个微服务,挨个去启动,现在一键compose部署。
-
安装docker compose
方式1️⃣:/usr/bin目录下
yum -y install docker-compose
#然后刷新配置
source /etc/profile
方式2️⃣:**/usr/local/bin**目录下
sudo curl -L https://download.fastgit.org/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
#然后赋予权限即可
sudo chmod +x /usr/local/bin/docker-compose
说明3️⃣:其本质上就是个二进制的文件。
- 运行compose指令
docker-compose up
#参数
-f, --file 指定使用的模板文件,默认为 docker-compose.yml,可以多次指定。
-p, --project-name NAME 指定项目名称,默认将使用所在目录名称作为项目名。
--verbose 输出更多调试信息。
swarm
0. 帮助文档
docker --help
docker images --help
范例
#参数有6个,其中两条拥有简写的形式
[root@VM-4-3-centos]$ docker logs --help
Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp
-n, --tail string Number of lines to show from the end of the logs
-t, --timestamps Show timestamps
--until string Show logs before a timestamp
relative (e.g. 42m for 42 minutes)
更多推荐
所有评论(0)