引言:
近期也是学习了下docker,特地记录下笔记来巩固知识,docker的安装我看其他博主都写得很好(注意一定要配置好可用的镜像,否则下载很慢或者失败),本文主要是讲解下核心语法,如果有的地方不准确还望多多包涵并在评论区指正。
一、Docker核心名词
三大核心要素:
1.仓库
专门用来存放镜像文件(类似软件市场)。
可以使用docker pull 镜像文件名来拉取镜像并保存在本地。(如果拉取官方,没指定的版本的话默认是最新版)
docker pull tomcat:8 (这种就是手动指定版本)
因为可能依赖jdk或者各种配置,所以实际安装的体积会大一些。
2.镜像(文件)
类似于安装包 ,描述运行所需要的环境配置 和依赖。
一个镜像 可以被多个容器运行
可以使用docker images来查看本地镜像缓存。
方式来源:
1.自己开发的springboot项目(需要自己创建镜像文件)。
2.通过官方dockerhub仓库来下载(较慢)。
3.一般通过国内加速镜像仓库来下载。
比如阿里云阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台 (每人会获得专门的镜像网址)参照这个可以配置一下,不过好像停用了,可以参考其他人推荐得。
可以使用docker info命令可以查看自己镜像是否配置成功。
docker search 镜像文件名(比如mysql) 可以查看官方仓库中含有的镜像。
docker rmi 镜像id(或者仓库名称也可以) 可以来删除镜像文件
3.容器
每个容器都有各自独立的ip和网络信息(实际上是一个轻量级的linux操作系统(比如centos))
专门用来运行镜像文件,拥有独立的ip和网络信息,可以虚拟化一个精简轻量级的linux版本。
docker ps 可以查看运行的容器
docker ps -a 可以查看所有容器(包含停止的)
docker run 镜像 注意: 一般需要指定容器名称,否则会一直创建新的容器(id不同)来运行镜像(如果镜像不存在也会自动下载)
docker stop 容器id可以停止掉
docker rm (可以写镜像id 或者名称 ) 可以删除容器
注意: 容器名称(Name)是不能重复的,所以我们docker run --name mypro1 镜像 之后想要再次运行的话要先停止,然后根据id删除,最后才能再次运行相同名称的容器(如果直接stop并docker run不指定名称的话,容器会一直创建而不使用)而且此时容器外部是无法访问的,。
curl ip:port 会拒绝连接,解决方法就是手动映射端口号:
docker run --name mayikt-tomcat -p 8081:8080 tomcat:8 (左边端口号我们可以任意修改,当然要注意不要让端口号冲突)
8081: 容器外部或者 linux 虚拟机访问的端口号 宿主机(容器外部可以访问的端口号)
8080: 容器内部的端口号(已经确定好的,比如tomcat内置的就是8080)
docker run --name mayikt-tomcat2 -p 8081:8080 -d tomcat:8 (最后还可以手动指定路径比如/bin/bash,不过dockerfile可能封装好了)
-d: 后台启动
前台启动与后台启动的区别: 前台启动 会打印启动日志信息; 后台启动不会打印启动日志信息
docker stop (docker ps -q) \& docker rm (docker ps -aq) ---删除所有的容器 (这个可能需要多执行几次,也可以分开执行)
docker rm $(docker ps -aq)这个就可以了,因为ctrl c可以全部停止掉
大致流程:

二、Docker和虚拟机的区别:


1.虚拟机是在硬件级别进行虚拟化,模拟硬件搭建操作系统;而Docker是在操作系统的层面虚拟化,复用操作系统,运行Docker容器。
2.Docker的速度很快,秒级,而虚拟机的速度通常要按分钟计算。
3.Docker所用的资源更少,性能更高。同样一个物理机器,Docker运行的镜像数量远多于虚拟机的数量。
4.虚拟机实现了操作系统之间的隔离,Docker是进程之间的隔离,虚拟机隔离级别更高、安全性方面也更强。
5.虚拟机和Docker各有优势,不存在谁替代掉谁的问题,很多企业都采用物理机上做虚拟机,虚拟机中跑Docker的方式。
三、制作镜像
这里是简单的在tomcat8中进入webapps写入文件来测试一下。
docker commit 根据当前容器制作镜像文件(首先需要有内容才行)。
1.进入正在运行的容器
docker exec -it 容器名(或容器id) bash。
ls可以列出目录中的文件和子目录。 然后可以再次cd进入文件(webapps)。
mkdir 文件名称(一般和仓库名称一致) 可以创建项目
2.手写内容
echo "hello" >> index.html (文件即使不存在也会自动创建) 可以直接将字符串写进创建的文件中。
cat index.html 可以将指定文件的内容打印在终端上。
之后可以 exit 退出容器。
3.commit制作镜像
根据当前容器作为模板制作为镜像文件
docker commit -m="描述信息" -a="作者" 正在运行的容器ID repository(仓库名称):1.0(TAG标签版本号)
docker run --name mayikt-tomcat2(然后再指定容器名称) -p 8088:8080 仓库名称:版本
运行之后就可以在浏览器中访问网址了
大致步骤:

http://虚拟机ip:8088/demo1/index.html
补充:

IMAGE(镜像)一般和REPOSITORY(仓库名称)名称相同
然后REPOSITORY和NAMES(容器名称)是独立的
四、Docker数据卷
pwd 可以显示当前目录的绝对路径
数据卷就是宿主机上的一个文件或目录
当容器目录和数据卷(宿主机)目录绑定,双方修改会立即同步操作
一个数据卷可以被多个容器同时挂载
数据卷作用:容器数据的持久化、外部机器和容器间接通信、容器之间数据交换,使用 -v 命令即可。
rm -rf 文件名称即可删除指定文件
mkdir -p /data/nginx/{conf,conf.d,html,logs} (-p自动递归创建目录)
docker run --name nginx81 -d -p 81:80 -v /data/nginx/html:/usr/share/nginx/html nginx 左边是容器外部路径和端口,而右边是容器中的外部和端口,期间只要在外部上传,那么内部也会同步更改,而且也可以docker exec -it 容器名(或容器id) bash 来查看是否更新文件了。
五、运行原理

我们下载的镜像底层可能依赖了其他镜像(利用unionfs技术),比如tomcat镜像依赖jdk镜像还有ubuntu镜像(像Centos等继承镜像一般都会继承过来),不过对外只暴露了tomcat镜像(所以下载后内存比较大)
而且如果我们再从官方下载镜像时,如果内部有对应的缓存,则会进行复用,不会再下载底层用到的镜像
六、DockerFile
DockerFile 是**镜像文件(Image)**的重要组成部分,是一个文本文件,描述镜像文件要具有依赖,需要哪些环境配置,如何启动等,用于定义如何构建镜像。
镜像文件(Image) 是通过 Dockerfile 构建出的二进制文件 ,是一个包含应用程序及其依赖环境的只读模板 。 它包含了运行应用所需的所有文件系统、代码、运行时、库、环境变量等,可直接用来创建容器。
流程如下: Dockerfile首先交给Docker打包(docker build )成镜像文件(安装包)最后再让Docker容器运行即可。
DockerFile 指令
-
FROM 指定父镜像: 基于哪个镜像 image 构建 指定基础镜像(比如依赖jdk环境)必须为第一个命令
-
MAINTAINER :维护者
-
RUN: 容器创建的时候执行一段命令 构建镜像时执行的命令
-
ADD: 将本地文件添加到容器中,tar 类型文件会自动解压(网络压缩资源不会被解压),可以访问网络资源,类似 wget
-
COPY:功能类似 ADD,但是是不会自动解压文件,也不能访问网络资源
-
CMD:构建容器后调用,也就是在容器启动时才进行调用。 .sh 执行文件(比如tomcat需要执行这个后缀文件)
-
ENV: 设置环境变量
-
EXPOSE: 指定于外界交互的端口
-
VOLUME 用于指定持久化目录
-
WORKDIR 设置进入容器时的路径 默认访问的目录
-
ENTRYPOINT 是固定的 "主命令",docker run 后的参数无法覆盖它(而 CMD 会被覆盖)。
DockerFile 编写规范
A.#描述注释 B.指令必须要大写,后面至少需要带至少一个参数; C.指令是按照从上到下,顺序执行;
docker run -it centos vim就是linux自带的文本编辑器
打包镜像文件
#继承docker hub 中的 centos 镜像文件(如果没有会先下载)
FROM centos
#自己定制的镜像文件作者
MAINTAINER mayikt-yushengjun
##配置环境变量MYPATH
ENV MYPATH /usr
##进入到容器中默认访问的目录/usr
WORKDIR $MYPATH
#安装下载vim
#更新软件源列表,获取最新的软件包信息
sudo apt update
#安装vim软件包,-y 选项同样表示自动确认安装
sudo apt -y install vim
##外部访问端口 80
EXPOSE 80
###启动成功容器之后 自动进入到容器中
CMD /bin/bash
docker build -f Dockerfile -t mycs:1 . (文件位置应该无所谓,但尽量规范,并且需要确保该目录下有Dockerfile文件)
Dockerfile -------配置文件(当前目录下找到名为Dockerfile的文件,如果名称是这个则可以省略)
mycs-----打包的镜像文件名称(Image也是仓库名)
.表示从当前目录构建
打包springboot项目
因为我们的项目中已经内置了tomcat,所以不需要继承
# 基础镜像使用java
FROM java:8
# 作者
MAINTAINER www.mayikt.com
# VOLUME 指定了临时文件目录为/tmp。
# 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp
VOLUME /tmp
# 将jar包添加到容器中并更名为mayikt.jar
ADD mayikt-thymeleaf-1.0-SNAPSHOT.jar mayikt.jar
# 运行jar包
# 通过 touch 命令确保文件有最新的时间戳,避免因文件时间戳过旧导致的潜在问题(尤其是在构建过程中复制的 jar 包可能保留原始时间戳的场景)。
RUN bash -c 'touch /mayikt.jar'
#["java", "-jar", "xxx.jar"] 这个核心结构是固定的
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/mayikt.jar"]
#暴露8080端口
EXPOSE 8080
然后再docker build即可
docker build和docker commit区别
相同点:都是构建镜像,使用完命令之后即可通过docker run来运行镜像。
docker build(推荐) 基于 Dockerfile 脚本 自动构建镜像。 Dockerfile 是一个文本文件,包含一系列系列指令(如 FROM、RUN、COPY 等),docker build 会按顺序执行这些指令,逐步构建出镜像层,最终生成新镜像。 整个过程是 可重复、可追溯 的(所有操作都记录在 Dockerfile 中)。 docker commit(临时) 基于 运行中的容器 的当前状态创建镜像。 简单来说,就是把容器当前的文件系统状态(包括所有手动修改)"快照" 下来,生成一个新镜像。 过程是 手动、不可追溯 的(无法明确知道镜像层的具体修改内容)。
七、Docker-Compose
Docker Compose能够实现容器编排技术(可以指定顺序启动多个容器也可以叫镜像,因为容器就是运行镜像的) (通过docker-compose.yml 来配置) 其实就是docker run的高级写法,然后也要注意编码统一成utf-8,不要出现上传时编码错误
区别: DockerCompose主要管理多个容器的编排和启动,而不是像docker build一样直接将dockerfile构建成Image
如果springboot项目依赖redis、mysql...等几十个容器,如果使用传统方式则需要每个都要单独docker run 单独启动(可能有的会启动失败),很复杂而且效率低。

version: "3.0"
services:
mysql: # mysql服务
image: mysql:5.7
command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
ports:
- "3306:3306" #容器端口映射到宿主机的端口
environment:
MYSQL_ROOT_PASSWORD: 'root'
MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
MYSQL_DATABASE: 'mayikt'
MYSQL_USER: 'mayikt'
MYSQL_PASSWORD: 'mayikt'
networks:
- mayikt_web
mayikt-web: #自己单独的springboot项目
hostname: mayikt
build: ./ #需要构建的Dockerfile文件(指定配置好的Dockerfile文件,可以按照该配置将jar包最终打成Image)
ports:
- "38000:8080" #容器端口映射到宿主机的端口
depends_on: #web服务依赖mysql服务,要等mysql服务先启动
- mysql
networks:
- mayikt_web
networks: ## 定义服务的桥
mayik
## 注意此时application.yml中配置mysql的连接地址写成jdbc:mysql://mysql:3306/...即可,这样会自动找到服务名称,而且是动态的,不能写死
## 而且此时创建后的mysql中数据库中还没有表,此时要么自己在创建一个,要么就是结合其他插件可以自动创建表
安装
然后目前我安装的是v2.24.6版本用得最多且稳定。(我是直接到github官网下载的,然后在用MobaXterm上传到linux即可)
1.mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose 移动并修改文件名字 cd .. 可以返回上一级目录
2.sudo chmod +x /usr/local/bin/docker-compose 添加可执行权限
3.docker-compose -v 验证是否成功
4.sudo chmod 777 /usr/local/bin/(这里的路径是一个例子) 可以设置所有权限,这样可以不用mv移动
5.sudo chmod 755 /usr/local/bin/ 然后再恢复原来的权限即可
Compose流程
-
需要在idea中定义一个 docker-compose.yml 文件----工程
-
需要在 docker-compose 文件配置依赖服务
-
docker-compose up 执行该文件(应该在存放docker-compose.yml的目录下执行该命令)

这里数据卷共享应该是容器内部和linux中的文件共享(我的docker安装在linux中,而linux在windows宿主机中)。访问网址没问题。
配置局域网
上述yml配置只是简单成功启动了,如果要实现容器间的访问(比如访问mysql)那么需要构建在同一个局域网下。
docker inspect 容器id(或name) 就可以查看容器的ip信息了。
也可以先进入正在运行的容器 docker exec -it 容器名(或容器id) bash 然后ip addr即可,进入之后也可以curl 另一个容器ip端口看看能否访问通过

注意:
1.Docker-Compose不是解决业务依赖之间的关系(大的公司中各种服务是项目隔离的,比如订单服务等,这些应该是spring cloud微服务来解决的,nacos服务注册(当然这时候我们的多个机器应该要在同一个局域网下才ok)),而是解决当前项目的环境配置。
可视化工具
docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer (自动启动成功)
这样运行后我们直接curl 宿主机ip(即我使用的ubuntu ip):9000即可测试,或者输入网址即可访问(第一次访问时注册密码即可)