Docker
概述
开发一个项目可能存在两种环境,开发、上线;两者需要配置的环境不同。
传统项目运行时,一个环境如 mysql 的错误会引发整个项目的宕机。
Docker 就是为了解决项目中不同的配置而产生,即可以同时将 jar、mysql、redis 等一起打包安装,称为镜像。
使用 Docker 生成镜像,下载安装即可使用。
思想:集装箱
Docker 核心思想:隔离,打包装箱,每个包都是相互隔离的。
Docker 能够最大限度的利用服务器的资源
虚拟化技术:
- 全虚拟、半虚拟、容器技术
虚拟机技术 => 容器化技术 容器化技术不是一个完整的操作系统
两者的优缺点和区别:
虚拟机技术:
- 资源占有率太高
- 步骤过多
- 启动慢
- 虚拟出一套硬件,拥有一个完整的操作系统,需要在该 OS 上安装相应的软件和环境
容器化技术:
- 容器应用直接运行在主体本机上,不拥有独立的内核
- 容器间相互隔离,每个容器拥有独立的文件系统,互不影响
- 内核级别的虚拟化
基本组成
镜像(image)
- 通过镜像可以创建多个容器
- 项目(服务)运行最终是在容器中运行的
容器(container)
- 利用容器技术,独立运行一个或一组 app
- 在初学阶段,可以将 container 理解为简易的 Linux 系统
仓库(repository)
- 存放镜像的位置
- repository 分为 public 和 private
- Docker Hub 类比 GitHub
安装
Centos
查看系统内核
# uname -r
5.10.112-11.1.al8.x86_64
查看系统版本
# cat etc/os-release
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"
CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"
安装步骤
更新
yum
索引
yum makecache fast
- 卸载旧版本
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine
- 下载相关工具及安装包
yum install -y yum-utils
- 配置镜像仓库
yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 安装 Docker 引擎
# docker-ce 社区版 yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
查看下载镜像
docker images
卸载
- 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io docker-compose-plugin
- 删除资源
# /var/lib/docker 默认工作路径 rm -rf /var/lib/docker rm -rf /var/lib/containerd
阿里云镜像加速
#
sudo mkdir -p /etc/docker
#
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://rl0hzmix.mirror.aliyuncs.com"]
}
EOF
#
sudo systemctl daemon-reload
#
sudo systemctl restart docker
Ubuntu
- 卸载旧版本
apt-get remove docker docker-engine docker.io containerd runc
- 更新
包索引apt
apt-get update
- 安装
依赖包,用于通过 HTTPS 来获取仓库apt
apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release
- 添加 Docker 官方 GPS 密钥
mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- 将 Docker 仓库添加到 APT 软件源
- 安装 Docker 引擎
apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
- 验证
docker --version
Docker 原理
Docker 工作原理
- Docker 是一个 C/S 结构的系统,其守护进程运行在本机,通过 Socket 从客户端访问
Docker 与 VM 的速度区别原因
- Docker 的抽象层比 VM 少;
- Docker 利用的是宿主机的内核,VM 需要使用 Guest OS(重新搭载)
常用命令
帮助命令
# 查看 Docker version
docker version
# 查看 Docker 信息(详细),system info,包括镜像和容器的数量
docker info
#
docker --help
镜像命令
# 查看镜像仓库
docker images
# 查看镜像仓库所有的镜像
docker images -a
# 查看镜像仓库中镜像的ID
docker images -q
# 参数配合使用
docker images -aq
搜索命令
# xxx表示镜像仓库中的镜像,如 mysql
docker search xxx
# 条件搜索,???表示查询的条件,可以是 STARS=3000
docker search xxx -filter=???
下载镜像
# xxx表示镜像仓库中的镜像,如:mysql,默认最新版本,tag表示版本号
docker pull xxx[:tag]
删除镜像
# 单个镜像删除,ID为 IMAGE ID,NAME 为 REPOSITORY,可以通过两种方式删除
docker rmi -f ID(NAME)
# 多个镜像删除
docker rmi -f $(docker images -qa)
容器命令
通过镜像启动容器
创建、启动
# args:
# --name "" 容器名字
# -d 后台方式运行
# -it 交互模式运行,进入容器
# -p 指定端口号,如:-p 8080:8080,不输入参数随机指定端口
# -p 主机端口:容器端口
# -p 容器端口
# -p ip:主机端口:容器端口
# image 是镜像的名
docker run [args] image
# e.g.
[[email protected] ~]# docker run -it centos /bin/bash
[[email protected] /]#
退出容器
# 容器停止并退出
exit
# 容器不停止退出
ctrl + P + Q
列出容器
# 列出当前正在运行的容器
docker ps
# 列出当前正在运行的容器、历史运行过的容器即所有容器
docker ps -a
# 最近创建的num个容器
docker ps -n=num
# 只显示编号
docker ps -q
删除容器
# 无法删除正在运行的容器
docker rm ID
# 删除所有容器
docker rm -f $(docker ps -aq)
docker ps -a -q|xargs docker rm
启动和停止
docker start ID
docker restart ID
# stop和kill的区别在于stop会给容器内的应用10s时间去停止服务,kill直接停止
docker stop ID
docker kill ID
start
和
run
的区别
-
:对镜像进行新建并运行run
-
:对关闭的容器进行运行(需存在)start
其他命令
查看日志
# 日志打印
# --tail num 显示的num条日志
docker logs -f -t --tail num containerID
# 所有日志
dokcer logs -tf containerID
# Shell 脚本
"while true;do echo Lyn-coder;sleep 1;done"
# 后台运行
docker run -d centos /bin/sh -c "while true;do echo Lyn-coder;sleep 1;done"
查看进程
# top
# docker top 2a7099f3b1d3
UID PID PPID C STIME TTY TIME CMD
root 14614 14594 0 19:14 ? 00:00:00 /bin/sh -c while true;do echo Lyn-coder;sleep 1;done
root 15104 14614 0 19:19 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
查看镜像元数据
# 查看容器的详细信息
docker inspcet containerID
进入容器
# 进入容器新终端
docker exec -it containerID /bin/bash
# 进入容器后使用,不开启新线程
docker attach containerID
拷贝
# container -> host
# docker cp 72446cb56e8b:/home/demo.java /home
docker cp containerID:dir dstDIr
测试实例
使用 Docker 安装 tomcat
# docker hub
# --rm 用于测试,使用完毕即删除容器
docker run -it --rm tomcat:9.0
# ====================
# run
docker run -d -p 8080:8080 --name tomcat_01 tomcat:9.0
# webapps 中没有任何文件,将 webapps.dist 文件夹中的文件 copy 到 webapps
# 就不会再是404的网页了
docker exec -it tomcat_01 /bin/bash
可视化界面
Pointer
:图形化界面管理工具
# 安装
docker run -d -p xxxx:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
镜像操作
commit
# 提交
docker commit -m="msg" -a="author" containerID 镜像名:版本
docker commit -a="Lyn-coder" -m="Tomcat webapps upgrade to test docker commit" 71b588888a1f tomcat_lyn:1.0
容器数据卷
简要
容器之间想要实现数据共享,Docker 容器中的数据可以同步到 host
目录的挂载,卷技术
目的:
- 数据持久化
- 容器同步操作
- 容器数据共享
使用
挂载
-v
# host-dir:主机目录位置
# container-dir:容器目录位置
docker run -it -v host-dir:container-dir containerID /bin/bash
Docker 与 MySQL
docker run -d -p xxxx:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=xxxxxx --name mysql_01 -d mysql
匿名与具名挂载
# -P 随机指定端口号,也可以指定端口号
# 匿名
docker run -d -P 容器内路径 镜像名
# 具名
docker run -d -P 卷名:容器内路径 镜像名
# all volume 卷
docker volume ls
# 卷具体信息
docker volume inspect 卷名
不指定目录时,Docker 容器中的卷,都存储在
/var/lib/docker/volumes/xxx/_data
匿名挂载、具名挂载、指定路径挂载的区分
- 匿名挂载
-v 容器内路径
- 具名挂载
-v 卷名:容器内路径
- 指定路径挂载
-v /host路径:容器内路径
参数补充
-
:read only,只读,只能从 host 对其进行操作,容器没有这个权限-ro
-
:read write,读写权限-rw
DockerFile
DockerFile
用来构建 Docker 镜像
标准文件命名为:
Dockerfile
# 文件命令需大写
FROM centos
VOLUME ["volume-01", "volume-02"]
CMD echo "===== end ====="
CMD /bin/bash
# 命令
docker build -f dockerfile-01 -t lyn/centos:1.0 .
# 执行
Sending build context to Docker daemon 2.048kB
Step 1/4 : From centos
---> 5d0da3dc9764
Step 2/4 : VOLUME ["volume-01", "volume-02"]
---> Running in 3e130dcabdb4
Removing intermediate container 3e130dcabdb4
---> 6b05c51c3970
Step 3/4 : CMD echo "===== end ====="
---> Running in 3a575a9f422b
Removing intermediate container 3a575a9f422b
---> 4e0a395ccac0
Step 4/4 : CMD /bin/bash
---> Running in fc17b239c866
Removing intermediate container fc17b239c866
---> 21e01bdb29b2
Successfully built 21e01bdb29b2
Successfully tagged lyn/centos:1.0
# TEST
# volume-01中创建一个 txt 文件
# 通过 inspect 查看 挂载位置
数据卷容器
两个及两个以上的容器进行数据同步
--volumes-from xxx
# 21e01bdb29b2:镜像ID
docker run -it --name docker-01 21e01bdb29b2
#
docker run -it --name docker-02 --volumes-from docker-01 21e01bdb29b2
# --volumes-from => 继承于
- 数据卷容器的生命周期:直到所有容器都被销毁
- 数据持久化到 host,本地数据不会被删除
DockerFile
构建镜像的步骤:
- 编写 DockerFile 文件
-
构建镜像docker build
-
发布镜像(Docker Hub/阿里云镜像仓库)docker push
DockerFile 原则
- 保留关键字必须是大写
- 执行顺序由上到下
- 注释使用
#
- 每一条指令都会创建并提交新的镜像层
- 面向开发,制作镜像发布项目需要编写 DockerFile 文件
DockerFile 指令
-
:指定基础镜像;FROM
-
:指定镜像作者,姓名+邮箱;MAINTAINER
-
:镜像构建运行命令;RUN
-
:增加镜像层;ADD
-
:设置镜像工作目录;WORKDIR
-
:设置挂载目录(卷);VOLUME
-
:设置暴露的端口,类比EXPOSE
;-p
-
:指定容器启动时运行的命令,只有最后一条命令生效;CMD
-
:指定容器启动运行的命令,可追加命令;ENTRYPOINT
-
:构建一个被继承的时候运行时的命令;ONBUILD
-
:将文件拷贝到镜像中;COPY
-
:设置环境变量;ENV
DEMO测试
# DockerFile
FROM centos
MAINTAINER author<email>
ENV MYPATH /usr/local
WORKDIR $MYPATH
# vim
RUN yum -y install vim
# ifconfig
RUN yum -y install net-tools
# 暴露端口
EXPOSE 80
# 打印
CMD echo $MYPATH
CMD echo "===== end ====="
CMD /bin/bash
=======================================================================
# 构建命令
docker build -f mydockerfile-centos -t lyn-mycentos:0.1 .
# 运行
docker run -f 镜像name -t 镜像[:tag] .
DEMO测试——Tomcat镜像
注:参考狂神的视频
步骤:
- 准备 JDK 和 Tomcat 的压缩包
- 编写 Dockerfile 文件
FROM centos:7 MAINTAINER author<email> COPY readme.md /usr/local/readme.md # 使用ADD命令会自动解压 ADD jdk-8u341-linux-x64.tar.gz /usr/local/ ADD apache-tomcat-9.0.65.tar.gz /usr/local/ # 安装vim RUN yum -y install vim # ENV MYPATH /usr/local WORKDIR $MYPATH # 配置环境变量 ENV JAVA_HOME /usr/local/jdk1.8.0_341 # 核心jar包 ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.65 ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.65 ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin # 容器内端口 EXPOSE 8080 # 容器启动时运行 CMD /usr/local/apache-tomcat-9.0.65/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.65/bin/logs/catalina.log
- 通过 Dockerfile 构建镜像
- 运行
docker run -d -p xxxx:8080 --name lyn-tomcat -v /home/xxx/build/tomcat/test:/usr/local/apache-tomcat-9.0.65/webapps/test -v /home/xxx/build/tomcat/tomcat-logs/:/usr/local/apache-tomcat-9.0.65/logs lyn-tomcat-images
在 webapps 文件夹的 test 文件夹中添加 WEB-INF 文件夹、jsp 和 xml 文件,注意:jsp 文件要与 WEB-INF 文件夹同目录
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta charset="utf-8">
<title>Hello World!</title>
</head>
<body>
<%-- JSP Comment --%>
<h1>Hello World!</h1>
<p>
<%
System.out.println("====== Lyn-Tomcat =======");
%>
</body>
</html>
<?xml version="1.0" encoding="utf-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd">
</web-app>
镜像发布
步骤
- Docker Hub 账号登录
docker login -u xxxx
- push
# 增加tag 原镜像名称 新镜像名称 docker tag xxx xxx # push docker push xxx:tag
发布到阿里云镜像
- 创建个人实例
- 创建命名空间
- 创建镜像仓库
- 根据阿里云中的文档 push 到阿里云镜像
Docker 网络
Docker0
使用
ip addr
,三个网卡:
-
:本机回环地址lo
-
:阿里云内网地址eth0
-
:Docker0地址docker0
# 查看容器内部 ip
docker exec -it xxxx ip addr
# 若出现 OCI runtime exec failed: exec failed: unable to start container process: exec: "ping": executable file not found in $PATH: unknown 报错
# 进入容器内部使用以下两条命令
apt-get update
apt-get install inetutils-ping
原理
- 每个 Docker 容器启动时,Docker 容器就会被分配到一个 ip;
- Docker 会带有一个网卡 Docker0,使用的模式是桥接模式,使用的技术是 **
**evth-pair
-
:一对虚拟设备接口,充当一个桥梁,连接虚拟网络设备exth-pair
-
- 容器在不指定网络的情况下,都是通过 Docker0 充当路由,Docker 会分配给容器可用的 ip;
- 核心是使用了 Linux 的虚拟化网络技术;
- Docker 中的网络接口都是虚拟的;
- 每个容器对应一对网桥;
--link
--link
原理
- 在容器中的
文件中增加对另一个容器的映射/etc/hosts
# 通过 --link 连接另一个容器,而不是用网络
docker run .... --link ConatinerName ...
# 例如tomcat
docker run -d -P --name docker-web-tomcat-01 --link docker-web-tomcat-01 tomcat
--link
在现实开发中已推荐使用
自定义网络
网络模式
-
:桥接模式(默认);bridge
-
:不配置网络;none
-
:和 host 共享网络;host
# 查看所有网络(Docker中)
docker network ls
# 自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
查看日志:
- 直接使用 run 命令运行,默认带有参数 --net bridge,即使用 bridge 模式,使用网卡 Docker0
- 自定义网路无需配置
,即可直接连接另一个容器--link
网络连通
相当于给容器再分配一个 ip
# 将 CONTAINER 连通到另一个网络
# 相当于把容器加入到网络的配置中
docker network connect NETWORK CONTAINER