一、docker的概念
1.什么是docker
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包(环境)到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
Docker将应用程序与该程序的依赖,打包在一个文件里面。运行这个文件,就会生成一个虚拟容器。程序在这个虚拟容器里运行,就好像在真实的物理机上运行一样。有了Docker,就不用担心环境问题。
总体来说,Docker的接口相当简单,用户可以方便地创建和使用容器,把自己的应用放入容器。容器还可以进行版本管理、复制、分享、修改,就像管理普通的代码一样。
Docker是开发人员和系统管理员使用容器开发、部署和运行应用程序的平台。使用Linux容器来部署应用程序称为集装箱化。使用docker轻松部署应用程序。
2.镜像(images)、容器(container)和仓库(DockerHub)
Docker中的三大名词:镜像(images)、容器(container)和仓库(DockerHub)
镜像: 通过运行镜像启动容器,一个镜像是一个可执行的包,其中包括运行应用程序所需要的所有内容-代码,运行时,库、环境变量和配置文件。
容器: 容器时镜像运行时示例-当被执行时(即,镜像状态,或者用户进程)在内存中,可以使用命令查看正在运行容器的列表docker ps,就像在Linux中一样。
仓库: DockerHub就相当于Maven的Repository,在Respository中存放是一个一个的jar包,而在DockerHub存放的是一个一个的镜像。
上面对于images(镜像)、容器的说法可能过于抽象,我们可以这么理解,你可以将images当做是java中的类,将容器当做是java中的对象,java中的一个类可以new出多个对象。在docker中,我们可以通过images(镜像)创建出多个容器。
3.docker与虚拟机的差别

一个容器中运行原生Linux和共享主机与其它容器的内核,它运行一个独立的进程,不占用任何其它可执行文件的内存,使其轻量化。
相比之下,虚拟机(VM)运行一个完整的“客户”操作系统,通过虚拟机管理程序虚拟访问主机资源。一般来说,虚拟机提供的环境比大多数应用程序需要的资源多。
二、docker安装
暂略
三、docker基本命令
1.镜像命令
(1)查看
docker images
docker images -a 展示所有镜像
docker images -q 只展示镜像的ID
(2)搜索
docker search 镜像
docker search 镜像 --filter=starts=3000
(3)下载
docker pull 镜像 :默认下载最新版本(latest)
docker pull 镜像:版本 :下载指定的版本
(4)删除
docker rmi -f 镜像ID:删除镜像
docker rmi -f $(docker images -aq) 批量删除所有镜像
2.容器命令
值得注意的是,我们有了镜像才可以创建容器。
(1)新建容器并启动
docker run [可选参数] 镜像
可选参数:
--name="名称" // 设置容器名
-d // 后台方式运行
-it // 使用交互方式运行,可以进入容器查看内容
-p //(小p), 指定容器端口
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用,将容器端口映射到主机端口)
-p 容器端口
-P //(大P), 随机指定容器端口
(2)列出运行中的容器
docker ps :查看正在运行的容器
docker ps -a:查看运行容器的历史记录
docker ps -a -n=2:查看最近运行的两个容器
docker ps -aq:查看所有容器的ID
(3)启动并停止容器
docker start 容器ID:启动容器
docker restart 容器ID:重启容器
docker stop 容器ID:停止容器
docker kill 容器ID:杀死容器
docker rm 容器ID :删除指定容器(不能删除正在运行的容器)
3.其他一些命令
(1)后台启动容器
docker run -d [镜像名]
可以通过
docker ps -a 显示所有运行的所有容器
进行查看
(2)查看日志
docker logs -tf --tail number 容器ID
-tf: 显示日志
--tail number :显示日志尾部的几条日志
(3)查看docker容器内部的进程信息
docker top 容器ID
(4)查看容器中的元数据
docker inspect 容器ID
(5)进入当前正在运行的容器
方式一:进入容器后,开启一个新的终端
docker exec -it 容器ID bashShell
方式二:进入当前正在执行的终端
docker attach 容器ID
(6)拷贝容器内的文件到本地
第一步:进入容器,并新建一个文件
第二步:退出容器,并拷贝容器内的文件到本地
exit // 退出
docker cp [容器id] 拷贝文件目录 目标目录 //拷贝
四、DockerFile
1. DockerFile介绍
dockerfile是用来构建docker镜像的文件(命令参数脚本)
构建步骤:
1.编写dockerfile文件
2.docker build 构建为一个镜像
3.docker run 运行镜像
4.docker push发布镜像(可以发布到Docker、阿里云镜像仓库)
2. DockerFile构建
基础知识:
1.每个保留关键字(指令)都必须是大写字母
2.执行从上到下顺序执行
3.#表注释
4.每一个指令都会创建提交一个新的镜像层并提交
- dockerfile是面向开发的,以后要发布项目做镜像就要编写dockerfile文件。Docker镜像逐渐成为了企业交付的标准,必须掌握。
- DockerFile:构建文件,定义了一切的步骤(自己写)
- DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品
- DockerContainer:容器是镜像运行起来提供服务的
3. DockerFile指令

- FROM #基础镜像,一切从这里开始构建 (如centos)
- MAINTAINER #镜像是谁写的,姓名+邮箱
- RUN #镜像构建的时候需要运行的命令
- ADD #步骤:要在centos下部署tomcat,就需要tomcat压缩包
- WORKDIR #镜像的工作目录
- VOLUME #挂载的目录
- EXPOSE #指定暴露端口(或通过-p来暴露)
- CMD #指定该容器启动时要运行的命令(只有最后一个会生效,可被替代)
-
ENTRYPOINT#指定该容器启动时要运行的命令(可追加命令)
ONBUILD#当构建一个被继承的DockerFile,此时会运行ONBUILD指令(触发指令)
COPY#类似ADD,将文件拷贝到镜像中
ENV#构建的时候设置环境变量
5.实战:Tomcat镜像
1.准备镜像文件tomcat压缩包,jdk的压缩包
tomcat下载地址:https://tomcat.apache.org/download-90.cgi
jdk下载地址:https://www.oracle.com/java/technologies/downloads/
2.编写dockerfile文件,官方命名 Dockerfile,build会自动寻找这个文件,就不需要-f 指定了
FROM centos:7.9.2009
MAINTAINER glh
COPY readme.txt /usr/local/readme.txt
ADD apache-tomcat-9.0.63.tar.gz /usr/local/
ADD jdk-18_linux-x64_bin.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk-18.0.1.1
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.63
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.63
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.63/bin/startup.sh && tail -F /url/local/apache-tomcat-9.0.63/bin/logs/catalina.out
遇到问题:
docker build时候报错:Error: Failed to download metadata for repo ‘appstream’: Cannot prepare internal mirrorlist: No URLs in mirrorlist
原因:原因:因为centOS8于2021年12月31日停止了源的服务,而现在时间是2022年3月了,所以之前的方法都不行的原因所在(本质是源的问题)。
解决办法:解决方案:未具体指明 centos7 的镜像时,它会默认去找最新的镜像,然后就一直失败
因为我的宿主机的是centos 7.9.2009的
因此在下载的时候下载了7.9.2009
docker pull centos:7.9.2009
将脚本中FROM centos改成指定版本FROM centos:7.9.2009
即可成功
3.构建镜像
docker build -t diytomcat .
4.启动镜像
docker run -d -p 9090:8080 --name glhtomcat
-v /usr/dockerTest/tomcat/test:/usr/local/apache-tomcat-9.0.63/webapps/test
# 将镜像内的/usr/local/apache-tomcat-9.0.63/webapps/test 目录挂载到本地的/usr/dockerTest/tomcat/test目录下
-v /usr/dockerTest/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.63/logs diytomcat
# 同理上
5.访问测试
进入启动的容器内查看
docker exec -it (容器名) /bin/bash
6.发布项目(由于做了卷挂载,可以直接在本地编写项目就可以发布)
index.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<titl>hello glh</title>
</head>
<body>
Hello World!<br/>
<%
System.out.println("my test tomcat");
%>
</body>
</html>
WEB-INF/web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
</web-app>
项目部署成功,可以直接访问!
以后开发的步骤:掌握Dockerfile编写,之后的一切都使用docker镜像来发布运行。
6.发布镜像
1.发布到DockerHub
1.注册账号 https://hub.docker.com/
2.登录并使用
docker login -umysteryuu
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
3.在服务器上提交镜像
docker tag da876eefca44 mysteryuu/diytomcat:1.0
先把要提交的镜像用tag改名为(用户名)/(镜像名):(版本号)否则会报错。
#报错
docker push diytomcat:latest
The push refers to repository [docker.io/library/diytomcat]
a5c8ab078e7f: Preparing
338960ad9da5: Preparing
3b1b1629ec9a: Preparing
5a04cd3ad5da: Preparing
174f56854903: Preparing
denied: requested access to the resource is denied
再用docker push把自己的镜像发布上去
docker push mysteryuu/diytomcat:1.0
The push refers to repository [docker.io/mysteryuu/diytomcat]
a5c8ab078e7f: Pushed
338960ad9da5: Pushed
3b1b1629ec9a: Pushed
5a04cd3ad5da: Pushed
174f56854903: Pushed
1.0: digest: sha256:58b1cf0c9c203324d913f685df4703a6eb68ac4f4e732fb15efbddbbe58ac69a size: 1373
2.发布到阿里云镜像服务上
1.登录阿里云
2.容器镜像服务
3.创建命名空间
4.创建容器镜像
5.浏览阿里云
7.小结
8.Docker网络
1.理解Docker0
ip addr命令查看三个网络
问题:docker是如何处理容器网络访问的?
#首先启动tomcat镜像
docker run -d -P --name tomcat01 tomcat
#查看容器的内部网络地址 ip addr,发现容器启动的时候会得到一个eth0
docker exec -it tomcat01 ip addr
问题:linux能否ping通容器内部?可以!
2.
原理:
1.每启动一个docker容器,docker就会给docker容器分配一个ip,只要安装了docker,就会有一个网卡docker0,桥接模式,使用的技术是evth-pari技术
可以发现80:eth0@if81和81:veth7705005@if80成对出现
**evth-pari技术:**就是一对的虚拟设备接口,成对出现,一段连着协议,一段彼此相连,正是因为这个特性,evth-pair充当一个桥梁,连接各种虚拟网络设备。OpenStac,Docker容器之间的连接,OVS的连接,都是使用evth-pair技术。
2.测试下tomcat01和tomcat02是否可以ping通?可以
docker exec -it tomcat02 ping 172.18.0.2
#结论:容器和容器之间可以相互ping通!
模型图:
结论:tomcat01和tomcat02共用一个路由器:docker0。
所有的容器不指定网络的情况下,都是docker0路由,docker会给容器分配一个默认的可用IP
Docker中的所有网络接口都是虚拟的,虚拟转发效率非常高。
只要容器删除,对应的网桥一对就会消失。
9.–link
思考一个场景:我们编写了一个微服务,database url=ip,项目在不重启的情况下,数据库ip换掉了,我们希望可以处理这个问题:可以通过名字来访问容器?
docker exec -it tomcat02 ping tomcat01
ping:tomcat01:Name or service not known
#如何解决?
docker run -d -P --name tomcat03 --link tomcat02 tomcat
#再启动一个tomcat03,同时用--link将其与tomcat02网络连通
#测试
docker exec -it tomcat03 ping tomcat02
#成功ping通
#反向可以ping通吗?
docker exec -it tomcat02 ping tomcat03
ping:tomcat03:Name or service not known
#不可以ping通
解释为什么不能反向ping通:
通过docker inspect (容器名)命令
进入tomcat03内部,查看/etc/hosts文件
可以看到tomcat02这个名与172.18.0.3绑定
–link就是在hosts配置文件中增加了一个172.18.0.3的映射
而在tomcat02内的/etc/hosts文件中没有配置tomcat03的映射
所以不能反向ping通
故在真实开发情况下,不建议使用–link,非常繁琐
docker0问题:不支持容器名连接访问,故需要自定义网络
10.自定义网络(容器互连)
查看所有的docker网络
docker network ls
网络模式
:
bridge:桥接模式(默认,自己创建也使用)
none:不配置网络
host:和宿主机共享网络
container:容器内网络连通(用的少)
测试:
#直接启动的命令 --net bridge,而这个就是docker0
docker run -d -P --name tomcat01 tomcat
#等效于(--net bridge是默认添加的)
docker run -d -P --name tomcat01 --net bridge tocat
#创建自定义网络
#--driver bridge
#--subnet 192.168.0.0/16
#--gateway 192.168.0.1
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
#自定义网络成功
docker network ls
NETWORK ID NAME DRIVER SCOPE
eb21272 mynet bridge local
查看自己创建的网络
#启动两个使用自定义网络的容器
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
此时再次查看自己创建的网络可以发现
#测试是否连通
docker exec -it tomcat-net-01 ping 192.168.0.3
#可以ping通
docker exec -it tomcat-net-01 ping tomcat-net-02
#可以ping通
我们自定义的网络docker都已经帮助我们维护好了对应关系,推荐平时这样使用网络。
好处
:
redis集群、mysql集群-不同的集群使用不同的网络,保证集群安全健康
11.网络连通
使用connect命令
#测试打通tomcat01-mynet
docker network connect mynet tomcat01
#再用inspect命令查看mynet网络配置
docker network inspect mynet
连通之后就是蒋tomcat01放到了mynet网络下。
也就是一个容器两个ip地址(好比阿里云服务器:公网ip和私网ip)
#测试
docker exec -it tomcat01 ping tomcat-net-01
#现在能成功ping通
docker exec -it tomcat02 ping tomcat-net-01
#tomcat02依旧ping不通
结论:假设需要跨网络操作别的容器,则需要使用docker network connect 连通。