文章目录
- 1 Docker理论
- 1.1 背景知识
- 1.2 是什么
- 1.3 Docker基本三要素
- 1.4 镜像原理
- 1.5 安装教程
- 2 Docker常用命令
- 2.0 防火墙相关命令
- 2.1 镜像命令
- 2.2 容器命令
- 2.3 进阶命令
- 3. 实战之Docker部署springboot项目
- 步骤一:Springboot项目配置
- 1.1 添加docker的maven依赖
- 1.2 新建Dockfile构建镜像
- 1.3 执行构建命令
- 步骤二 启动docker镜像
- 步骤三:访问测试
- 坑:镜像无法启动
- 4. 实战之Dockerfile编写指南
1 Docker理论
1.1 背景知识
**传统软件开发与运维痛点:**一款产品从开发到上线,从操作系统到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验。Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装? 也就是说,安装的时候,把原始环境一模一样地复制过来,消除协作编码时“在我的机器上可正常工作,在他人机器上不能运行”的问题。
从而打破之前开发人员只提供代码(代码即应用)的方式,改为提交Docker镜像包括(运行文档、配置环境、运行环境、运行依赖包、操作系统发行环境),即镜像即应用。
1.2 是什么
Docker是基于Go语言实现的云开源项目。Docker的主要目标是"Build,Ship and Run Any App,Anywhere",也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP (可以是一个WEB应用或数据库应用等)及其运行环境能够做到“一次封装,到处运行”。
Linux容器技术的出现就解决了这样一个问题,而Docker就是在它的基础上发展过来的。将应用运行在Docker容器上面,而Docker容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署,大大简化了操作。
与虚拟机的区别?
虚拟机(virtual machine)就是带环境安装的一种解决方案。它可以在一种操作系统里面运行另一种操作系统,比如在Windows系统里面运行Linux系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。
虚拟机的缺点:
1、资源占用多 2、冗余步骤多 3、启动慢(分钟级别)
1.3 Docker基本三要素
仓库Repository + 镜像Image + 容器Container
仓库Repository—>镜像Image(类Person)–>容器Container(对象p1、p2)
- 仓库Repository是存放镜像文件的场所,仓库Repository与仓库注册器Registry是有区别的,仓库注册服务器上往往存放多个仓库,每个仓库有多个镜像,每个镜像有不同的标签tag(仓库分为公开仓库public和私有库private,最大的仓库Docker Hub,但由于其服务器在国外,从中拉去镜像速度很慢,国内一般使用的是阿里云、网易云。)
- 镜像Image就是从docker Hub仓库拉取到本地的一个只读的模版,镜像Image用来创建容器Container,一个镜像可以创建多个容器
镜像Image(类)—>容器Container(对象) - Docker本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎image镜像文件。只有通过这个镜像文件才能生成Docker容器(集装箱)。
1.4 镜像原理
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。
UnionFS (联合文件系统) : Union文件系统(UnionFS) 是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
1.5 安装教程
1. Docker官网:https://www.docker.com
2. Docker Hub官网:https://hub.docker.com
3. MAC安装教程:https://docs.docker.com/desktop/install/mac-install/
4. LinuxC安装教程
# 1.移除以前docker相关包
yum remove docker*
# 2.配置yum源
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 3.安装docker并启动
sudo yum install -y docker-ce docker-ce-cli containerd.io # 安装docker及其组件
yum install -y docker-ce-20.10.7 docker-ce-cli-20.10.7 containerd.io-1.4.6 # 以下是在安装k8s的时候使用,暂时不安装
systemctl enable docker --now # 启动docker,并设置开机自启动,首次优先使用该命令
service docker status # 查看状态
service docker start # 启动
service docker stop # 停止
# 4.配置加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
2 Docker常用命令
2.0 防火墙相关命令
sudo firewall-cmd --list-all --zone=public # 查看防火墙对外提供访问的接口
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent # 开放TCP端口80(HTTP)
sudo firewall-cmd --zone=public --remove-port=80/tcp --permanent # 关闭TCP端口80(HTTP
sudo firewall-cmd --permanent --query-port=80/tcp # 查看端口是否开启
service firewalld status
service firewalld stop
service firewalld start
service firewalld restart
2.1 镜像命令
1 帮助命令:
docker version
docker info
docker --help
2 镜像命令:
1、列出本地镜像:docker images [-options]
-a:列出本地所有镜像
-q:只显示镜像ID
--digests:显示镜像的摘要信息
--no-trunc:显示完整的镜像信息
docker images -a
docker images -q
2、查询DockerHub镜像:docker search [-options] 镜像名
docker search tomcat:列出tomcat的镜像
docker search --no-trunc tomcat:显示完整的镜像描述
3、下载镜像到本机:docker pull 镜像名
docker pull tomcat 下载最新镜像tomcat,等同于docker pull tomcat:latest
docker pull redis:6.2.4 下载指定版本镜像
4、删除本机镜像:docker rmi -f 镜像名/镜像id
docker rmi [-f] tomcat
2.2 容器命令
容器命令:有镜像才能实例化容器(提前下载一个centos镜像仅有200MB)
1、新建并启动一个容器:docker run [-options] 具体镜像名称:版本号 /bin/bash:
--name:容器的新别名
-i:以交互方式启动容器,通常与-t同时使用
-t:为容器分配一个伪输入终端
-d:以守护进程方式启动容器
以交互方式启动容器(为主):前台启动
docker run –it --name my-centos centos:7 /bin/bash
以守护进程方式启动容器:运行在后台
docker run -d --name=mynginx --restart=always -p 88:80 nginx
2、列出所有正在运行的容器: docker ps [-options]
-l:显示最近创建的容器
-n 2:显示最近2个创建的容器
-a:显示当前多元的正在运行的容器+历史上运行过的
-q:静默模式,只显示容器编号
--no-trunc:不截断输出显示
3、退出容器
exit: 在容器内,关闭该容器并推出
ctrl+P+Q: 在容器内,关闭该容器但是不推出
4、停止容器 docker stop 容器名称或容器id
5、强制停止容器 docker kill容器名称或容器id
6、重启容器 docker restart 容器名称或容器id
7、删除容器 docker rm 容器名称或容器id
8、查看容器日志 docker logs [-options] 容器名称或容器id
docker logs -f 3063af3e3f86
2.3 进阶命令
1、进容器内部
docker exec -it 容器id /bin/bash # 在新的容器中打开新的命令终端,可以启动新的进程
2、挂载数据到外部修改
docker run --name=mynginx \
-d --restart=always \
-p 88:80 \
-v /data/html:/usr/share/nginx/html:ro \ # 修改页面只需要去主机的 /data/html
nginx:latest
3、镜像分享方案一
docker save -o mynginx.tar nginx # 将镜像保存成压缩包
docker load -i abc.tar # 别的机器将压缩包加载为镜像
4、镜像分享方案二【需要docker hub账号】
docker commit -m "首页变化" 341d81f7504f guignginx:v1.0 # 将自己修改好的镜像提交
在docker hub 注册仓库
docker tag guignginx:v1.0 leifengyang/guignginx:v1.0 # 把旧镜像的名字,改成仓库要求的新版名字
docker login # 登录到docker hub
docker push leifengyang/guignginx:v1.0 # 推送
docker logout # 推送完成镜像后退出
docker pull leifengyang/guignginx:v1.0 # 别的机器下载
5、查看容器运行情况
docker top 容器名称或容器id # 查看容器内运行的进程
docker inspect 容器名称或容器id # 查看容器内部细节
docker attach 容器名称或容器id # 进入正在运行的容器并以命令行交互, 不会启动新的进程
6、从容器内拷贝文件到主机上:
docker cp 容器id: 容器路径 目的主机路径
3. 实战之Docker部署springboot项目
需求:
- 手动部署:本地IDE打包成jar,在docker环境中创建java环境容器,将jar包使用命令行拷贝至docker容器中,启动。
- 自动部署:通过Maven插件配置参数自动部署。(优先选这个)
步骤一:Springboot项目配置
1.1 添加docker的maven依赖
<plugins>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<configuration>
<imageName>docker/${project.artifactId}</imageName> <!-- 镜像名称 -->
<dockerDirectory>src/main/docker</dockerDirectory> <!-- Dockerfile文件存放目录:后续改为项目根目录,后续Dockfile文件一定要放在这 -->
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
</plugin>
<!--这个插件,可以将应用打包成一个可执行的jar包-->
<!--千万不能丢掉,不然web项目没有main入口-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.2</version>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
1.2 新建Dockfile构建镜像
# 基于openjdk 镜像,如果镜像不是本地的会从 DockerHub 进行下载
FROM openjdk:8
# VOLUME 指向了一个/tmp的目录,由于 SpringBoot使用内置的Tomcat容器,Tomcat 默认使用/tmp作为工作目录。
# 这个命令的效果是:在宿主机的/var/lib/docker目录下创建一个临时文件并把它链接到容器中的/tmp目录
VOLUME /tmp
# 作者
MAINTAINER zhupeng
# 将本地JAR包打包到容器中,并重命名
ADD springboot-1.0-SNAPSHOT.jar app.jar
# 声明需要暴露的端口 在Dockerfile中声明了那些端口是需要开放的,在构建容器时通过-p可以随机映射端口,如果EXPOSE没有指定端口,那么使用-p参数无效。本配置只是声明,一般我们需要在构建docker容器时使用-p(小写的p)指定开放的端口。
EXPOSE 8080
# 配置容器启动后执行的命令
ENTRYPOINT ["java","-jar","app.jar"]
1.3 执行构建命令
mvn clean package -Dmaven.test.skip=true docker:build # 前提要有docker环境
PS:如果还win执行mvn指令:mvn clean package ‘-Dmaven.test.skip=true’
步骤二 启动docker镜像
docker images -a
docker run -d --name my-springboot -p 8080:8080 docker/springboot-multipart [务必指定暴露端口]
docker ps -a
docker logs -f 976e5ee13513ed3
步骤三:访问测试
http://10.1.42.71:8080/test/show
坑:镜像无法启动
如果没连接数据库的话,是可以正常启动的,但是如果application.yml连接了数据库,那就会无法启动。
Host '10.1.42.71' is not allowed to connect to this MySQL server" MySQL不允许远程登录
解决方案:
1. update user set host = '%' where user = 'root'; 会警告报错
2. UPDATE `mysql`.`user` SET `Host` = '%' WHERE (`Host` = 'localhost') and (`User` = 'root');
或者手动改
use mysql;
Select user from mysql.user; MySQL 服务器中所有用户的列表
mysql -u root -h 10.1.42.71 -p: MySQL远程登录
4. 实战之Dockerfile编写指南
https://zhuanlan.zhihu.com/p/143109114
Dockerfile中文名叫镜像描述文件,是一个包含用于组合镜像目录的文本文档,也可以叫“脚本”。他通过读取Dockerfile中的指令安装步骤自动生成镜像。
补充:文件名称必须是:Dockerfile
基础命令
# 1. FROM
# 制作基础镜像:基于openjdk 镜像
FROM openjdk:8
# 2. MAINTAINER
# 谁创造了它(作者信息)
MAINTAINER zhupeng
# 3. WORKDIR
# 类似于Linux中的cd命令:cd高级的地方在于,若发现没有这个目录,就自动创建出来,建议使用绝对路径
WORKDIR /usr/local/testdir
# 4.COPY
# 文件拷贝
# 案例一:将1.txt拷贝到根目录下。它不仅仅能拷贝单个文件,还支持Go语言风格的通配符,比如如下:
COPY 1.txt /
# 案例二:拷贝所有 abc 开头的文件到testdir目录下
COPY abc* /testdir/
# 案例三:? 是单个字符的占位符,比如匹配文件 abc1.log
COPY abc?.log /testdir/
# 5.ADD
# 往它肚子里放点文件(会自动解压)
ADD springboot-1.0-SNAPSHOT.jar app.jar
# 案例一:将1.txt拷贝到根目录的abc目录下。若/abc不存在,则会自动创建
ADD 1.txt /abc
# 案例二:将test.tar.gz解压缩然后将解压缩的内容拷贝到/home/work/test
ADD test.tar.gz /home/work/test
# docker官方建议当要从远程复制文件时,尽量用curl/wget命令来代替ADD。因为用ADD的时候会创建更多的镜像层。镜像层的size也大。
# ADD/COPY对比
# 1.二者都是只复制目录中的文件,而不包含目录本身。
# 2.COPY能干的事ADD都能干,甚至还有附加功能。
# 3.ADD可以支持拷贝的时候顺带解压缩文件,以及添加远程文件(不在本宿主机上的文件)
# 4.只是文件拷贝的话可以用COPY,有额外操作可以用ADD代替。
# 6.ENV
# 设置环境常量,方便下文引用
ENV JAVA_HOME /usr/local/jdk1.8
RUN ${JAVA_HOME}/bin/java -jar xxx.jar
# 7.RUN
# RUN指令是在构建镜像时运行,在构建时能修改镜像内部的文件[docker::build]
# SHELL命令格式:RUN yum -y install vim
# EXEC命令格式: RUN ["yum","-y","install","vim"]
# SHELL:当前shell是父进程,生成一个子shell进程去执行脚本,脚本执行完后退出子shell进程,回到当前父进程。
# EXEC:用EXEC进程替换当前进程,并且保持PID不变,执行完毕后直接退出,不会退回原来的进程。
# 总结:也就是说shell会创建子进程执行,EXEC不会创建子进程。推荐EXEC命令格式
# 8.CMD
# 1.容器启动时执行,而不是镜像构建时执行[docker run]
# 2.Dockerfile中只有最后一个ENTRYPOINT会被执行,推荐用EXEC格式。
# 3.重点在于如果容器启动的时候有其他额外的附加指令,则CMD指令不生效。
# 9.ENTRYPOINT
# 容器创建时执行,而不是镜像构建时执行。
# Dockerfile中只有最后一个ENTRYPOINT会被执行,推荐用EXEC格式。
ENTRYPOINT ["java","-jar","app.jar"]
# 给我一个存放行李的地方(目录挂载):将本地文件夹挂载到当前容器
VOLUME /tmp
# 声明需要暴露的端口
EXPOSE 8080