docker学不会?no,no,no,有时候你缺的只是一篇博客而已!
docker大全,全是干货,赶紧整起来吧!
Docker 进阶篇
Docker入门
什么是Docker?为什么要用docker?相关概念: Docker常用命令
Docker 帮助指令:镜像 *** 作命令:容器 *** 作命令: Docker网络
docker的网络模式docker 自定义网络:容器的端口暴露 Docker数据卷
数据卷的使用场景数据卷实验
创建数据卷清理数据卷实验展示: 数据卷容器 Dockerfile
**构建步骤:****基础知识:**dockerfile 分层原理:dockerfile指令:优化方式:发布自己的镜像
1、我们先 push 到dockerHub上:2、镜像push到阿里云上:
Docker入门 什么是Docker?Docker 是世界领先的软件容器平台。Docker 属于 Linux 容器的一种封装,提供简单易用的容器使用接口。Docker 将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了 Docker,就不用担心环境问题。
像我们经常说的“在我的机器上可以正常运行,到你的机器上就不行”,这个一般都是环境引起的。而docker可以完美的解决这个问题。
为什么要用docker?容器除了运行其中应用外,基本不消耗额外的系统资源,使得应用的性能很高,同时系统的开销尽量小。传统虚拟机方式运行 10 个不同的应用就要起 10 个虚拟机,而Docker 只需要启动 10 个隔离的应用即可。
docker优势:
1、更快速的交付和部署;
2、更高效的虚拟化;
3、更轻松的迁移和扩展;
4、更简单的管理;
相关概念:Docker是CS架构;
Docker daemon: 运行在宿主机上,Docker守护进程,用户通过Docker client(Docker命令)与Docker daemon交互Docker client: Docker 命令行工具,是用户使用Docker的主要方式,Docker client与Docker daemon通信并将结果返回给用户,Docker client也可以通过socket或者RESTful api访问远程的Docker daemon。
了解一下Docker的三个主要概念:
Docker image:镜像是只读的,镜像中包含有需要运行的文件。镜像用来创建container,一个镜像可以运行多个container;镜像可以通过Dockerfile创建,也可以从Docker hub/registry上下载。Docker container:容器是Docker的运行组件,启动一个镜像就是一个容器,容器是一个隔离环境,多个容器之间不会相互影响,保证容器中的程序运行在一个相对安全的环境中。Docker hub/registry: 共享和管理Docker镜像,用户可以上传或者下载上面的镜像,官方地址为https://registry.hub.docker.com/,也可以搭建自己私有的Docker registry。
镜像就相当于打包好的版本,镜像启动之后运行在容器中,仓库就是装存储镜像的地方。
Docker常用命令 Docker 帮助指令:在 *** 作docker时,我们常需要输入一些指令,那这些指令怎么用呢?
这里我们可以借助官方文档进行查看指令的用处;(这里我们需要登入一下dockerhub ,没有的话我们就注册一个);
另外,我们也可以在docker中查看指令怎么用;
#查看帮助指令 docker 指令 --help
镜像 *** 作命令:
#下载镜像 docker pull 镜像名[:tag] docker pull centos:7 #如果不指定tag,默认是pull最新的 latest
也可以去官网 pull 镜像
https://hub.docker.com/_/centos?tab=tags
#查看镜像的信息: docker images #获取镜像信息 docker inspect 镜像ID #有些时候我们pull下来的镜像,在自己这添加了一些功能后,可以为其添加标签在 push到dockerhub上 #为镜像添加标签: #如,为nginx:latest 镜像添加标签 docker tag nginx:latest nginx:lnmp
当我们不需要某些镜像时,我们还可以删掉某些镜像:
#删除镜像 docker rmi 镜像名或ID #删除镜像标签 docker rmi 镜像名:tag #还可以批量删除所有镜像 docker rmi `docker images -q` #这里的-q 只会输出镜像ID [root@docker ~]#docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest 605c77e624dd 2 weeks ago 141MB hello-world latest feb5d9fea6a5 3 months ago 13.3kB [root@docker ~]#docker images -q 605c77e624dd feb5d9fea6a5
有些时候,我们自己创建的镜像,如果在没网的情况下,要使用的话,我们就需要先把他导出来,在没网的时候导进去即可;
#镜像的导出导入 docker save -o 文件名 镜像名 示例: docker save -o nginx_docker nginx:latest #镜像导入 docker load < nginx_docker
镜像导出导入的意义?
Docker镜像的导入导出,用于迁移、备份、升级等场景;若是只想备份images,使用save、load即可;若是在启动容器后,容器内容有变化,需要备份容器,则使用export、import;
当我们从 docker 镜像仓库中下载的镜像不能满足我们的需求时,我们可以通过以下两种方式对镜像进行更改。
1、从已经创建的容器中更新镜像,并且提交这个镜像2、使用 Dockerfile 指令来创建一个新的镜像
容器 *** 作命令:
首先安装好docker和启动docker:
#运行容器 docker run hello-world #卸载docker #删除安装包: yum remove docker-ce #删除镜像、容器、配置文件等内容 rm -rf /var/lib/docker
我们可以自己创建容器:
#创建容器 docker create -it nginx:latest /bin/bash #-i:提供一个 *** 作容器的接口 #-t:是一个伪终端,使 *** 作容器有个落脚点 #/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash。
在创建完容器后,我们要启动他:
#启动容器 docker start 容器id #停止容器 docker stop 容器ID #有些时候我们可以在创建的时候就启动它 #并在启动后让他执行一些指令,列如:-c 后面表示要执行的命令 docker run -it centos:7 /bin/bash -c ls / #但它是一次性的,执行完后就会退出
#查看docker 相关信息 docker version #或者 docker info docker inspect 容器name(id)
启动容器的几种方式:
#启动容器: #这种情况会在你退出容器时而停止容器运行 docker run -it nginx:latest /bin/bash #持续后台运行容器,这里借助了死循环语句 docker run -d centos:7 /bin/bash -c "while true;do echo hello;done" #查看所有容器 docker ps -a #查看所有容器id docker ps -aq
但在大部分的场景下,我们希望 docker 的服务是在后台运行的,我们可以过 -d 指定容器的运行模式。
#注意:这里加-d 不会进入容器; docker run -itd centos:7 /bin/bash #进入容器 docker exec -it 容器ID /bin/bash exec下(容器必须为开启状态)
三种运行容器的区别:
docker run -it会创建前台进程,但是会在输入exit后终止进程。docker attach 会通过连接stdin,连接到容器内输入输出流,会在输入exit后终止容器进程。docker exec -it 会连接到容器,可以像ssH一样进入容器内部,进行 *** 作,可以通过exit退出容器,不影响容器运行。
#容器的导出与导入 #容器导出 docker export 容器ID >文件名 示例: docker export nginx:latest >nginx_a #容器导入(生成镜像) docker import 导出的文件名(容器)指定镜像名称 示例: docker import nginx_a nginx:latest cat 文件名(容器)| docker import - nginx:latest
##删除容器 docker rm 容器工D docker rm `docker ps -aq` #强制删除容器(正在运行的) docker rm -f 容器ID #批量删除容器(正则匹配) docker ps -a awk '{print "docker rm "} ' l bash#删除非up状态的rm -f强制删除 docker rm `docker ps -q` #批量删除"exit"状态(指定状态)的容器 for i in `docker ps -a | grep -i exit | awk '{print }'; do docker rm -f$i; done #查询所有当前容器资源消耗信息 docker stats 容器ID #查看容器信息: docker inspect 容器id #搜索容器: docker search 容器name #查询最后一次创建的容器: docker ps -lDocker网络
前面我们实现了通过网络端口来访问运行在 docker 容器内的服务。
容器中可以运行一些网络应用,要让外部也可以访问这些应用,可以通过 -P 或 -p 参数来指定端口映射。
首先了解docker网络之前我们先看看宿主机上有哪些网卡:
1、lo:回环网卡;检测TCP/IP是否生效
2、ens33网卡:宿主机网卡,只有centos7是叫ens33,其他linux发行版都是eth0网卡;
3、virbr0网卡:是服务器硬件网卡;
4、docker 0:容器的网关,绑定物理网卡,负责做NAT地址转换、端口映射;docker0本身也是一种容器;
另外还有就是 weth-pair对:
veth对:一组虚拟设备,用户连接两个不同的名称空间;宿主机内就是veth;
这都是一对一对出现的,如 9: vethd8e28c8@if8,11: vethd058aa4@if10;
docker的网络模式Host模式:-net=host;容器和宿主机共享Network namespace(网络名称空间/网络协议栈)。Container模式:-net=container:NAME or ID;多个容器共享一 个Network namespace 。None模式:-net=none;容器有独立的Network namespace,但并没有对其进行任何网络设置,如分配veth pair和网桥连接,配置IP等(自闭空间)。Bridge模式:-net=bridge(默认为该模式);默认模式通过Veth对连接容器与docker0网桥,网桥分配给容器IP,同时docker0作为“局域网“内容器的网关,最后和宿主机网卡进行通讯。
这些都是docker自带的,除了这些,我们还可以对docker 自定义网络;
docker 自定义网络:docker network ls ##查看网络列表 #还可以查看容器网关,IP,端口等信息 docker inspect 容器ID
这里默认的都是从172.17.0.1/16 开始,
接下来我们自定义网络:
首先了解一下自定义网络的好处:
1、如果我们用docker默认的网络,当我们的容器停止修改优化后,再上线时IP会换成其他的IP,不再是原来的那个IP,这会导致访问不到我们的业务,并可能照成业务瘫痪。
2、为了解决这种情况,我们就需要自定义网络,让每个容器有自己的IP,即使容器老掉线,但只要再次上线,他就还是原来的那个IP。
#指定分配容器IP地址 docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:latest /bin/bash --network:指定网络类型 --ip:指定ip地址 #注意:这里会报错,因为这是容器默认给的IP,不可以修改
我们要先自定义一个网络,才可以给他固定的IP;
#自定义网络,固定IP docker network create --subnet=172.18.0.0/16 mynetwork #先自定义个网络 docker run -itd --name test02 --net mynetwork --ip 172.18.0.100 centos:latest /bin/bash #这里就可以给容器指定IP了
在我们配置到IP后,我们要将业务暴露出去,给别人访问,例如:我们这有一个nginx服务容器,那我们怎么才能让别人访问到我们的容器呢?
这里我们就需要将我们的nginx容器的服务端口暴露到宿主机上,这样别人访问我们 宿主机IP:暴露端口 就可以访问到我们的业务了。
#暴露端口 #-p自定义端口(宿主机端口:容器内端口) docker run -itd -p 90:80 nginx:latest /bin/bash #-P随机端口(-P 49153起始,49153到65535) docker run -itd -P nginx:latest /bin/bash
#我们把nginx运行起来看看效果 docker exec 684f2a3263d8 nginx
这里的随机端口也是这样测试的,只不过随机端口不用指定端口映射,他默认从49153开始;
不过要注意的是,当你随机了一个容器端口映射后,再把这个容器删掉,之后在创建容器随机映射端口后,他会从下一个开始,一直这样下去,不会有重复的;并且这里的随机端口也是伪随机,他是从49153开始一直排下去的;
Docker数据卷在Docker中,要想实现数据的持久化(所谓Docker的数据持久化即***数据不随着Container的结束而结束***),需要将数据从宿主机挂载到容器中。目前Docker提供了三种不同的方式将数据从宿主机挂载到容器中:
(1)volumes:Docker管理宿主机文件系统的一部分,默认位于 /var/lib/docker/volumes 目录中;(最常用的方式)
(2)bind mounts:意为着可以存储在宿主机系统的任意位置;(比较常用的方式)
但是,bind mount在不同的宿主机系统时不可移植的,比如Windows和Linux的目录结构是不一样的,bind mount所指向的host目录也不能一样。这也是为什么bind mount不能出现在Dockerfile中的原因,因为这样Dockerfile就不可移植了。
(3)tmpfs:挂载存储在宿主机系统的内存中,而不会写入宿主机的文件系统;(一般都不会用的方式)
数据卷的使用场景在多个容器之间共享数据,多个容器可以同时以只读或者读写的方式挂载同一个数据卷,从而共享数据卷中的数据。当宿主机不能保证一定存在某个目录或一些固定路径的文件时,使用数据卷可以规避这种限制带来的问题。当你想把容器中的数据存储在宿主机之外的地方时,比如远程主机上或云存储上。当你需要把容器数据在不同的宿主机之间备份、恢复或迁移时,数据卷是很好的选择。
数据卷实验docker 专门提供了 volume 子命令来 *** 作数据卷:
#我们通过--help指令来看下 volume怎么使用 docker volume --help Usage: docker volume COMMAND Commands: create 创建数据卷 inspect 显示数据卷的详细信息 ls 列出所有的数据卷 prune 删除所有未使用的 volumes,并且有 -f 选项 rm 删除一个或多个未使用的 volumes,并且有 -f 选项创建数据卷
docker volume create 卷名 #查看卷 docker volume ls #详细查看 docker volume inspect 卷名
有了自定义容器卷,我们可以创建一个使用这个数据卷的容器,这里我们以nginx为例:
docker run -itd --name=nginx01 -v nginx_vol:/usr/share/nginx/html nginx
其中,-v代表挂载数据卷,这里使用自定数据卷nginx_vol,并且将数据卷挂载到 /usr/share/nginx/html (这个目录是yum安装nginx的默认网页目录)。
如果没有通过-v 指定,那么Docker会默认帮我们创建匿名数据卷进行映射和挂载。
清理数据卷如果不再使用自定义数据卷了,那么可以手动清理掉:
docker stop nginx01 #暂停容器实例 docker rm nginx01 #// 移除容器实例 docker volume rm nginx_vol #// 删除自定义数据卷实验展示:
docker pull nginx #宿主机目录/mnt 挂载容器中的/data01 #注意:这里的data01 容器中没有他会自己创建 docker run -v /mnt:/data01 --name nginx01 -itd nginx /bin/bash #进入容器中创建文件检测 docker exec -it 59403edfdabe /bin/bash ls cd /data01 touch 1.txt #在宿主机中的 /mnt 目录下查看
注意:上面的 vim 不可以用,是因为容器中的centos还没有这个功能,要自己 yum install -y vim;
数据卷容器容器间数据同步
这里我们启动三个容器:
我们让centos01 容器作为父容器;centos02和centos03作为子容器:
docker run --name centos01 -v /data01 -it centos:7 /bin/bash docker run -it --volumes-from centos01 --name centos02 centos:7 /bin/bash docker run -it --volumes-from centos01 --name centos03 centos:7 /bin/bash
接下来我们来测试一下:
在父容器中创建数据,在两个子容器中查看:
通过上面结果我们看出,在 /data01 这个目录下的数据是共享的,无论是谁在这里写数据,其他容器都可以看到;
这个 /data01 目录还挂载在我们的宿主机,所以容器间的共享数据就可以持久化的保存下来。
这里有个小问题:怎么把宿主机的文件传入到容器内部呢?
哎,这里我们可以借助docker cp 指令。
#docker cp 源文件路径 容器ID:目标文件位置 [root@docker ~]#docker cp --help Usage: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|- docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH #这里通过 --help 知道有两种写法,那种简单选那种就可以 docker cp /opt/2.txt a9a03fc65822:/data01 #然后我们去centos01 查看
dockerfile 是用来构建docker镜像的文件!命令参数脚本!
构建步骤:1、编写一个dockerfile 文件;
2、docker bulid 构建成为一个镜像;
3、docker run 运行镜像;
4、docker push 发布镜像(dockerHub公共仓库,阿里云镜像仓库);
1、每个保留关键字(指令)都必须是大写字母
2、指令是从上到下顺序执行
3、# 表示注释
4、每一个指令创建提交都会产生一个新的镜像层
docker镜像分层(基于AUFS构建),AUFS是文件联合系统;
Docker镜像位于bootfs之上;
每一层镜像的下一层成为父镜像;
第一层镜像成为base image( *** 作系统环境镜像)容器层(可读可写),在最顶层(writable);
容器层以下都是readonly;
contaier 读写层(可读可写)
images (只读)
base image
bootfs +rootfs + aufs/overlay2 +LXC (kernel)
bootfs + rootfs :作用是加载、引导内核程序+挂载使用linux *** 作系统(centos ubantu)等等一些关键的目录文件;
对于一个精简的os,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel;
自己只需要提供rootfs就行了。由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,
因此不同的发行版可以公用bootfs;
AUFS和 overlay:
AUFS是一种联合文件系统。它使用同一个Linuxhost上的多个目录,逐个堆叠起来,对外呈现出一个统一的文件系统。
AUFS使用该特性,实现了Docker镜像的分层;
docker 使用了overlay/overlay2存储驱动来支持分层结构;
overlayFs将单个Linux主机上的两个目录合并成一个目录。这些目录被称为层,统一过程被称为联合挂载
overlay结构:
overlayfs在linux主机上只有两层,一个目录在下层,用来保存镜像(docker),另外一个目录在上层,用来存储容器信息。
FROM #基础镜镜像,—切从这里开始构建 MAINTAINER #镜像是谁写的,姓名+邮箱 RUN #镜像构建的时候需要运行的命令 ADD #步骤: tomcat镜像,这个tomcat压缩包!添加内容 WORKDIR #镜像的工作目录 VOLUME #挂载的目录 EXPOSE #暴露端口 CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可被替代 ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令 onBUILD # 当构建一个被继承 DockerFile这个时候就会运行ONBUILD的指令。触发指令。 COPY #类似ADD,将我们文件拷贝到镜像中 ENV #构建的时候设置环境变量!
镜像构建完后,我们还可以查看镜像构建过程:
#查看镜像构建过程: docker history 镜像ID
在知道Dockerfile 怎么编写后,我们来尝试写一个Dockerfile:
我们就写一个简单的Dockerfile 文件:
vim Dockerfile FROM centos:7 RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make ADD nginx-1.12.0 /opt WORKDIR /opt/nginx-1.12.0 RUN ./configure --prefix=/usr/local/nginx RUN make && make install EXPOSE 80 VOLUME ["/usr/local/nginx/html"] CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off"] #编写好Dockerfile文件后,我们要去构建镜像 docker build -f Dockerfile文件位置 -t 镜像名 . #这里若果我们编写的镜像文件是 Dockerfile的话,那就可以省略不写,因为这是官方的写法,他会自己去找Dockerfile文件,还有就是要注意后面的这一个点,不能忘记; docker build -t nginx:v1 . #构建好镜像后,我们就来运行这个容器 docker run -d -p 90:80 nginx:v1
有提到指令最后一个 . 是上下文路径,那么什么是上下文路径呢?
上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
这里我们自己编写的dockerfile 文件构建出来的镜像有472MB,相比我们pull nginx的话,显然是有点大的,那他们是怎么做到的呢?
这里我们就得说下Dockerfile 的优化了;
因为docker 镜像是分层思想,每层他都会有缓存,上一层构建时可能会用到下层的缓存,所以层数越多,他站的缓存也就越多,所以构建完后的大小就越大;
在编写Dockerfile 时,都是一层一条指令的;
所以要想大小变小,我们可以优化层数,减少 RUN 指令的使用;
优化方式:1、减少RUN 指令的使用;
2、将执行后的缓存/不用的输出丢入黑洞 (减少缓存);
3、多阶段构建;
4、使用更小体积的linux发行版本;更加轻量级的centos的版本;
发布自己的镜像当我们编写好一个 Dockerfile 文件,构建好镜像,运行容器后,觉得非常好用,这时候我们就可以 push 到 dockerHub 上或者阿里云上,给别人使用,或者作为私有仓库保存到里面,用到的时候在pull 下来。
如:我编写好一个Tomcat的Dockerfile 后,我想push到dockerHub和阿里云上,可以这样做:
#我编写的Dockerfile 文件 vim Dockerfile FROM centos:7 ADD apache-tomcat-9.0.16.tar.gz /opt/tomcat ADD jdk-8u201-linux-x64.tar.gz /opt/tomcat ENV JAVA_HOME /opt/tomcat/jdk1.8.0_201/ ENV CATALINA_HOME /opt/tomcat/apache-tomcat-9.0.16 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin EXPOSE 8080 CMD ["/opt/tomcat/apache-tomcat-9.0.16/bin/catalina.sh","run"] #构建镜像和运行容器 docker build -t tomcat:v1 . docker run -d -p 9090:8080 tomcat:v11、我们先 push 到dockerHub上:
先去docker官网注册自己的账号;https://www.docker.com/
在我们的服务器上push镜像:
#我们查看一下怎么登录 docker login --help Usage: docker login [OPTIONS] [SERVER] Options: -p, --password string Password --password-stdin Take the password from stdin -u, --username string Username #docker login -u 用户名 password: #密码
出现登录成功后,我们就可以push 自己的镜像了;
#首先我们要添加个 tag,带上你的用户名 docker tag 镜像ID 名字:tag docker tag 5ceee19144d9 tiks821/tomcat:v1 #然后在push 上去,不然会报错 docker push tiks821/tomcat:v1 #没有添加用户名 tag,报的错信息: denied: requested access to the resource is denied
这里服务器push到dockerHub上是非常慢的,因为dockerHub 服务器在国外,我们的网络是比较吃力的;
所以针对这种情况,我们就把镜像 push到阿里云上;
2、镜像push到阿里云上:01、我们得登录阿里云;
02、搜索容器镜像服务;
这里我们前面用过阿里的容器镜像加速;
03、我们创建自己的个人实例:
04、创建好后我们进入个人实例,创建命名空间和镜像仓库:
注意:这里的名称空间每个用户只能创建三个;
05、镜像仓库创建好后,我们就可以push 镜像了;
这里我们可以看阿里云给的文档,他会告诉我们怎么 push 镜像;
接下来我们来push 我们的镜像;
#首先是登录阿里云 docker login --username=萧楚河 registry.cn-hangzhou.aliyuncs.com #然后添加 tag,这里跟dockerHub一样,都要添加tag docker tag 镜像ID registry.cn-hangzhou.aliyuncs.com/tiks/studydocker:tomcat_v1 #最后push 镜像 docker push registry.cn-hangzhou.aliyuncs.com/tiks/studydocker:tomcat_v1
再去阿里云上看,就会有我们push的镜像了;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)