docker的那些事儿 docker?
wptr33 2024-11-12 14:21 14 浏览
在Linux(Ubuntu)中安装docker
- apt-get remove docker docker-engine docker.io containerd runc
- apt update
- apt-get install ca-certificates curl gnupg lsb-release
- curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
- add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
- apt-get install docker-ce docker-ce-cli containerd.io
- 中途出现问题的话,使用 sudo apt-get update 试试
- systemctl start docker
- apt-get -y install apt-transport-https ca-certificates curl software-properties-common
- service docker restart
- docker run hello-world
- docker version
docker常用命令
帮助命令
docker version # 显示Docker版本信息
docker info # 显示Docker系统信息,包括镜像和容器数量
docker --help # 帮助文档
镜像命令
docker images [options] # 列出本地主机上的镜像
# options
-a: 列出本地所有镜像
-q: 只显示镜像id
docker search [image name] [options] # docker search 某个镜像的名称(对应DockerHub仓库中的镜像)
# options
--filter=stars=50 # 列出收藏数不小于指定值的镜像
docker pull [image name]:[tag] # 下载镜像
docker image rm -f [image name or image id]... # 删除一个或多个镜像
docker image rm -f $(docker images -aq) # 删除本地全部镜像
docker image inspect [image id] # 查看镜像元数据
docker history [image id or image name] # 列出镜像的变更历史
docker login -u [username] # 登录dockerhub
docker push chrishi/mycentos:1.0 # 将镜像发布出去
容器命令
docker run [options] image [command]
# options
--name="Name" # 给容器指定一个名字
-d # 后台方式运行容器,并返回容器的id
-i # 以交互模式运行容器,通常和-t一起使用
-t # 给容器重新分配一个终端,通常和-i一起使用
-P # 随机端口映射(大写)
-p # 指定端口映射(小写),一般可以有四种写法
ip:hostPort:containerPort
ip::containerPort
hostPort:containerPort (常用)
containerPort
docker run -it centos /bin/bash # 使用centos用交互模式启动容器, 在容器内执行/bin/bash命令
# 使用exit退出容器
docker ps [options] # 列出所有运行的容器
# options
-a # 列出当前所有正在运行的容器+历史运行过的容器
-l # 显示最近创建的容器
-n=? # 显示最近n个创建的容器
-q # 只显示容器编号
exit # 容器停止退出
ctrl+P+Q # 容器不停止退出
docker start [container id or container name] # 启动容器
docker restart [container id or container name]# 重启容器
docker stop [container id or container name] # 停止容器
docker kill [container id or container name] # 强制停止容器
docker rm [container id] # 删除指定容器
docker rm -f $(docker ps -aq) # 删除所有容器
docker ps -a -q|xargs docker rm # 删除所有容器
docker logs [options] [container id] # 查看容器日志
# options
-t # 显示时间戳
-f # 打印最新的日志(follow log output)
--tail 数字 # 显示多少条
docker top [container id] # 查看容器中运行的进程信息
docker inspect [container id] #查看容器的元数据
docker exec -it [container id] [bash shell] # 进入正在运行的容器(是在容器中打开新的终端,并且可以启动新的进程)
docker attach [container id] # 直接进入容器启动命令的终端,不会启动新的进程
docker cp 容器id:容器内路径 目的主机路径 # 从容器内拷贝文件到主机上
docker commit -m="提交的描述信息" -a="作者" 容器id 要创建的目标镜像名:[标签名] # 从容器创建一个新的镜像
容器数据卷
挂载方式一:容器中直接使用命令来挂载
docker run -it -v 宿主机绝对路径目录:容器内目录 镜像名 /bin/bash
# eg
docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
挂载方式二:通过Docker File 来挂载
# Dockerfile
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "-------end------"
CMD /bin/bash
docker build -t chrisshi/centos .
匿名和具名挂载
# 匿名挂载
-v 容器内路径
docker run -d -P --name nginx01 -v /etc/nginx nginx
# 匿名挂载的缺点,就是不好维护,通常使用命令 docker volume维护
docker volume ls
# 具名挂载 -v 卷名:/容器内路径
docker run -d -P --name nginx02 -v nginxconfig:/etc/nginx nginx
docker volume inspect nginxconfig # 查看挂载的路径
# 怎么判断挂载的是卷名而不是本机目录名?
不是/开始就是卷名,是/开始就是目录名
Dockerfile
基础知识
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
- 指令按照从上到下,顺序执行
- #表示注释
- 每条指令都会创建一个新的镜像层,并对镜像进行提交
构建步骤
- 编写Dockerfile文件
- docker build 构建镜像
- docker run
构建过程
- docker从基础镜像运行一个容器
- 执行一条指令并对容器做出修改
- 执行类似docker commit 的操作提交一个新的镜像层
- docker再基于刚刚提交的镜像运行一个新容器
- 执行Dockerfile中的下一条指令直到所有指令都执行完成
Dockerfile指令
FROM # 基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER # 镜像维护者的姓名混合邮箱地址
RUN # docker build 时需要运行的命令
EXPOSE # 当前容器对外保留出的端口
WORKDIR # 指定在创建容器后,终端默认登录的进来工作目录,一个落脚点
ARG # docker build 时Dockerfile文件中的变量
ENV # docker run 时设置环境变量
COPY # 拷贝文件和目录到镜像中
ADD # 功能与COPY一样,但是多了自动解压文件的功能
VOLUME # 容器数据卷,用于数据保存和持久化工作
CMD # docker run 时要运行的命令,Dockerfile中可以有多个CMD指令,但只有最后一个生效
ENTRYPOINT # docker run 时要运行的命令,和CMD一样
ONBUILD # 当构建一个被继承的Dockerfile时运行命令,父镜像在被子镜像继承后,父镜像的ONBUILD被触发
CMD:Dockerfifile 中可以有多个CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换!
ENTRYPOINT: docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合!
实例
背景:官方默认的centos镜像默认路径是 / ,默认不支持vim,默认不支持ifcofig
目的:使我们自己的镜像具备如下: 登录后的默认路径(/usr/local)、vim编辑器、查看网络配置ifconfig支持
# Dockerfile
FROM centos:7
MAINTAINER chris.shi<sxy0129@yeah.net>
ENV MYPATH /usr/local
WORKDIR $MYPATH
RUN yum update
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "--------end--------"
CMD /bin/bash
# 构建
# docker build -t 新镜像名字:TAG .
docker build -t my-centos:1.0 .
# 运行
# docker run -it 新镜像名字:TAG
docker run -it mycentos:1.0
# 列出镜像的变更历史
docker history [image id]
docker 网络讲解
理解docker0
原理
- 每一个安装了docker的linux主机都有一个docker0的虚拟网卡。这个是桥接网卡,使用了veth-pair技术
root@chris-virtual-machine:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:7a:47:5a brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 192.168.32.128/24 brd 192.168.32.255 scope global dynamic noprefixroute ens33
valid_lft 5529035sec preferred_lft 5529035sec
inet6 fe80::7a87:6135:1c98:61a9/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:8c:f2:d0:2d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:8cff:fef2:d02d/64 scope link
valid_lft forever preferred_lft forever
4: br-89830bc6a152: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:78:e0:07:c8 brd ff:ff:ff:ff:ff:ff
inet 192.168.0.1/16 brd 192.168.255.255 scope global br-89830bc6a152
valid_lft forever preferred_lft forever
- 每启动一个docker容器,linux主机就会多一个虚拟网卡
# 我们启动了一个tomcat01(172.17.0.2),主机的ip地址多了一个 24: vethf840e91@if23
docker run -d -P --name tomcat01 tomcat
# 然后我们在tomcat01容器中查看容器的ip是 23: eth0@if24
docker exec -it tomcat01 ip addr
# 我们再启动一个tomcat02(172.17.03)观察
docker run -d -P --name tomcat02 tomcat
# 然后发现linux主机上又多了一个网卡 26: vethe152c3e@if25
# 我们看下tomcat02的容器内ip地址是 25: eth0@if26
# veth-pair 就是一对虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。
# 正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备!
# “Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络 结构,比如 OpenStack Neutron。
- 测试tomcat01和tomcat02容器间是否可以互相ping通
root@0f3b19b75279:/usr/local/tomcat# ping 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: icmp_seq=0 ttl=64 time=2.966 ms
64 bytes from 172.17.0.3: icmp_seq=1 ttl=64 time=0.164 ms
64 bytes from 172.17.0.3: icmp_seq=2 ttl=64 time=0.171 ms
# 结论:容器和容器之间是可以互相访问的
- 结论
tomcat1和tomcat2共用一个路由器。是的,他们使用的一个,就是docker0
任何一个容器启动默认都是docker0网络
docker默认会给容器分配一个可用ip
- 小结
- Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接通信。 Docker容器网络就很好的利用了Linux虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫veth pair)
- Docker中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。
--Link
- 思考一个场景,我们编写一个微服务,数据库连接地址原来是使用ip的,如果ip变化就不行了,那我们能不能使用服务名访问呢?
jdbc:mysql://mysql:3306,这样的话哪怕mysql重启,我们也不需要修改配置了!docker提供了 --link 的操作!
# 我们使用tomcat02,直接通过容器名ping tomcat01,不使用ip, 发现是ping不通的
# 我们再启动一个tomcat03,但是启动的时候连接tomcat02
docker run -d -P --name tomcat03 --link tomcat02 tomcat
# 这个时候,我们就可以使用tomcat03 ping通tomcat02了
docker exec -it tomcat03 ping tomcat02
# 再来测试,tomcat03是否可以ping通tomcat01 失败
# 再来测试,tomcat02是否可以ping通tomcat03 反向也ping不通
- 思考,这个原理是什么呢?我们进入tomcat03中查看下host配置文件
root@f86e6836e0a1:/usr/local/tomcat# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 tomcat02 a263c1e773b2 # 发现tomcat2直接被写在这里
172.17.0.4 f86e6836e0a1
# 所以这里其实就是配置了一个 hosts 地址而已! # 原因:--link的时候,直接把需要link的主机的域名和ip直接配置到了hosts文件中了
--link早都过时了,我们不推荐使用!我们可以使用自定义网络的方式
自定义网络
基本概念
root@chris-virtual-machine:~# docker network --help
Usage: docker network COMMAND
Manage networks
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
所有网络模式
网络模式 | 配置 | 说明 |
bridge模式 | --net=bridge | 默认值,再docker网桥docker0上为容器创建新的网络栈 |
none模式 | --net=none | 不配置网络,用户可以稍后进入容器,自行配置 |
container模式 | --net=container:name/id | 容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个Network namespace |
host模式 | --net=host | 容器和宿主机共享Network namespace |
用户自定义 | --net=自定义网络 | 用户自己使用network相关命令定义网络,创建容器的时候可以指定为自己定义的网络 |
# 1. 删除原来的所有容器
docker rm -f $(docker ps -aq)
# 2. 接下来我们来创建容器,但是我们知道默认创建的容器都是docker0网卡的
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0网络的特点 1.它是默认的 2.域名访问不通 3.--link 域名通了,但是删了又不行
# 3. 我们可以让容器创建的时候使用自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
docker network ls
docker network inspect mynet
# 4. 我们来启动两个容器测试,使用自己的 mynet!
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
docker network inspect mynet
# 5. 我们来测试ping容器名和ip试试,都可以ping通
docker exec -it tomcat-net-01 ping 192.168.0.3
docker exec -it tomcat-net-01 ping tomcat-net-02
发现,我们自定义的网络docker都已经帮我们维护好了对应的关系
所以我们平时都可以这样使用网络,不使用--link效果一样,所有东西实时维护好,直接域名 ping 通
网络联通
docker0和自定义网络肯定不通,我们使用自定义网络的好处就是网络隔离
那关键的问题来了,如何让 tomcat-net-01 访问 tomcat1?
# 1. 启动默认的容器,在docker0网络下
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat
# 2. 我们来测试一下!打通mynet-docker0
docker network connect mynet tomcat01
docker network inspect mynet # 发现我们的tomcat01就进来这里了,tomcat01拥有了双ip
# 3. tomcat01 可以ping通了
docker exec -it tomcat01 ping tomcat-net-01
# 4. tomcat02 依旧ping不通,大家应该就理解了
结论:如果要跨网络操作别人,就需要使用 docker network connect [OPTIONS] NETWORK CONTAINER 连接
相关推荐
- 【推荐】一款开源免费、美观实用的后台管理系统模版
-
如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍...
- Android架构组件-App架构指南,你还不收藏嘛
-
本指南适用于那些已经拥有开发Android应用基础知识的开发人员,现在想了解能够开发出更加健壮、优质的应用程序架构。首先需要说明的是:AndroidArchitectureComponents翻...
- 高德地图经纬度坐标批量拾取(高德地图批量查询经纬度)
-
使用方法在桌面上新建一个index.txt文件,把下面的代码复制进去保存,再把文件名改成index.html保存,双击运行打开即可...
- flutter系列之:UI layout简介(flutter ui设计)
-
简介对于一个前端框架来说,除了各个组件之外,最重要的就是将这些组件进行连接的布局了。布局的英文名叫做layout,就是用来描述如何将组件进行摆放的一个约束。...
- Android开发基础入门(一):UI与基础控件
-
Android基础入门前言:...
- iOS的布局体系-流式布局MyFlowLayout
-
iOS布局体系的概览在我的CSDN博客中的几篇文章分别介绍MyLayout布局体系中的视图从一个方向依次排列的线性布局(MyLinearLayout)、视图层叠且停靠于父布局视图某个位置的框架布局(M...
- TDesign企业级开源设计系统越发成熟稳定,支持 Vue3 / 小程序
-
TDesing发展越来越好了,出了好几套组件库,很成熟稳定了,新项目完全可以考虑使用。...
- WinForm实现窗体自适应缩放(winform窗口缩放)
-
众所周知,...
- winform项目——仿QQ即时通讯程序03:搭建登录界面
-
上两篇文章已经对CIM仿QQ即时通讯项目进行了需求分析和数据库设计。winform项目——仿QQ即时通讯程序01:原理及项目分析...
- App自动化测试|原生app元素定位方法
-
元素定位方法介绍及应用Appium方法定位原生app元素...
- 61.C# TableLayoutPanel控件(c# tabcontrol)
-
摘要TableLayoutPanel在网格中排列内容,提供类似于HTML元素的功能。TableLayoutPanel控件允许你将控件放在网格布局中,而无需精确指定每个控件的位置。其单元格...
- 12个python数据处理常用内置函数(python 的内置函数)
-
在python数据分析中,经常需要对字符串进行各种处理,例如拼接字符串、检索字符串等。下面我将对python中常用的内置字符串操作函数进行介绍。1.计算字符串的长度-len()函数str1='我爱py...
- 如何用Python程序将几十个PDF文件合并成一个PDF?其实只要这四步
-
假定你有一个很无聊的任务,需要将几十个PDF文件合并成一个PDF文件。每一个文件都有一个封面作为第一页,但你不希望合并后的文件中重复出现这些封面。即使有许多免费的程序可以合并PDF,很多也只是简单的将...
- Python入门知识点总结,Python三大数据类型、数据结构、控制流
-
Python基础的重要性不言而喻,是每一个入门Python学习者所必备的知识点,作为Python入门,这部分知识点显得很庞杂,内容分支很多,大部分同学在刚刚学习时一头雾水。...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mysql max (33)
- vba instr (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)