Docker不会?不,你缺的是一篇博客( •̀ ω •́ )✧

Docker不会?不,你缺的是一篇博客( •̀ ω •́ )✧,第1张

Docker不会?不,你缺的是一篇博客( •̀ ω •́ )✧ Docker 进阶篇

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 -l
Docker网络

前面我们实现了通过网络端口来访问运行在 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

dockerfile 是用来构建docker镜像的文件!命令参数脚本!

构建步骤:

1、编写一个dockerfile 文件;
2、docker bulid 构建成为一个镜像;
3、docker run 运行镜像;
4、docker push 发布镜像(dockerHub公共仓库,阿里云镜像仓库);

基础知识:

1、每个保留关键字(指令)都必须是大写字母
2、指令是从上到下顺序执行
3、# 表示注释
4、每一个指令创建提交都会产生一个新的镜像层

dockerfile 分层原理:

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),另外一个目录在上层,用来存储容器信息。

dockerfile指令:
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:v1
1、我们先 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的镜像了;


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5703861.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存