docker的那些事儿 docker?
wptr33 2024-11-12 14:21 19 浏览
在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 连接
相关推荐
- C++企业级开发规范指南(c++开发gui)
-
打造高质量、可维护的C++代码标准一、前言C++作为一门功能强大的系统级编程语言,被广泛应用于操作系统、游戏引擎、高性能服务器、数据库系统等领域。知名互联网公司(如Google、Microsoft、腾...
- C++|整型的最值、上溢、下溢、截断、类型提升和转换
-
整数在计算机内以有限字长表示,当超出最值(有限字长)时,需要截断(溢出,求模)操作。不同字长的整型具有不同的值域,混合运算时,需要类型提升和转换。1整形最值在<limit.h>中有整型的...
- C++|漫谈STL细节及内部原理(c++ std stl)
-
1988年,AlexanderStepanov开始进入惠普的PaloAlto实验室工作,在随后的4年中,他从事的是有关磁盘驱动器方面的工作。直到1992年,由于参加并主持了实验室主任BillWo...
- C++11新特性总结 (二)(c++11新特性 pdf)
-
1.范围for语句C++11引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素vector<int>vec={1,2,3,4,5,6};f...
- C++ STL 漫谈(c++中的stl到底指的什么)
-
标准模板库(StandardTemplateLibrary,STL)是惠普实验室开发的一个函数库和类库。它是由AlexanderStepanov、MengLee和DavidRMusser在...
- C++学习教程_C++语言随到随学_不耽误上班_0基础
-
C++学习教程0基础学C++也可以,空闲时间学习,不耽误上班.2019年C语言新课程已经上线,随到随学,互动性强,效果好!带你征服C++语言,让所有学过和没有学过C++语言的人,或是正准备学习C++语...
- C++遍历vector元素的四种方式(c++ 遍历vector)
-
vector是相同类型对象的集合,集合中的每个对象有个对应的索引。vector常被称为容器(container)。C++中遍历vector的所有元素是相当常用的操作,这里介绍四种方式。1、通过下标访问...
- 一起学习c++11——c++11中的新增的容器
-
c++11新增的容器1:array当时的初衷是希望提供一个在栈上分配的,定长数组,而且可以使用stl中的模板算法。array的用法如下:#include<string>#includ...
- C++编程实战基础篇:一维数组应用之投票统计
-
题目描述班上有N个同学,有五位候选人“A,B,C,D,E”,请所有的同学投票并选举出班长,现在请你编写程序来他们计算候选人的得票总数,每位同学投票将以数字的形式投票“12345”分别代表五位候选人,...
- C++20 新特性(6):new表达式也支持数组大小推导
-
new表达式也支持数组大小推导在C++17标准中,在定义并初始化静态数组时,是可以忽略数组大小,然后通过初始化数据来推导数组的大小。但使用new来定义并初始化动态数组时,并不支持这种自动推导数组大...
- C++ 结构体(struct)最全详解(c++结构体用法)
-
一、定义与声明1.先定义结构体类型再单独进行变量定义structStudent{intCode;charName[20];charSex;intA...
- 自学 C++ 第 6 课 二维数组找最值
-
键盘输入一个m×n的二维数组,通过C++编程找出元素中的最大值,并输出其所在的位置坐标。例如,输入一个4×5的二维数组,数组元素分别为{{556623749},{578964563},...
- 从缺陷中学习C/C++:聊聊 C++ 中常见的内存问题
-
在写C/C++程序时,一提到内存,大多数人会想到内存泄露。内存泄露是一个令人头疼的问题,尤其在开发大的软件系统时。一个经典的现象是,系统运行了10天、1个月都好好的,忽然有一天宕机了:OOM(Out...
- C++开发者都应该使用的十个C++11特性(上)
-
在C++11新标准中,语言本身和标准库都增加了很多新内容,本文只涉及了一些皮毛。不过我相信这些新特性当中有一些,应该成为所有C++开发者的常规装备。你也许看到过许多类似介绍各种C++11特性的文章。下...
- 深度解读C/C++指针与数组(c++指针和数组的区别)
-
指针和数组是密切相关的。事实上,指针和数组在很多情况下是可以互换的。例如,一个指向数组开头的指针,可以通过使用指针的算术运算或数组索引来访问数组。今天我们就来聊一聊数组和指针千丝万缕的关系;一维数组与...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
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)
- 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)
- c语言 switch (34)
- git commit (34)