【狂神说Java】Docker最新超详细版教程通俗易懂
视频地址:https://www.bilibili.com/video/BV1og4y1q7M4
Docker基础
Docker概述
开发完成一个项目,需要运行起来,不同的机器,不同的环境,都需要配置一套运行环境,十分麻烦。这就需要一个东西来管理带上这些运行所需要的环境。
-
java开发apk,发布到应用软件,然后下载安装即可。
-
java开发jar,打包项目和环境(镜像),然后在Docker商店下载即可
Docker容器技术,也是一种虚拟化技术,例如虚拟机Vmware。但是虚拟机十分笨重,它是虚拟出来了一整套的操作系统内核,占了几十个G;但是Docker很轻巧,容器技术只隔离应用程序的运行时环境,但容器之间可以共享同一个操作系统
DevOps(开发,运维):更快速的交付和部署,更便捷的升级和扩容缩容,更简单的系统运维,更高效的计算资源利用
基本组成:
docker使用了常见的C/S架构,也就是client-server模式,docker client负责处理用户输入的各种命令,比如docker build、docker run,真正工作的其实是server,也就是docker daemon守护线程,值得注意的是,docker client和docker demon可以运行在同一台机器上。
- Dockerfile:包含构建Docker映像的指令(命令)的文本文件。
- Docker Image:从Dockerfile创建的容器的快照。映像存储在注册表中,如Docker Hub,并且可以从注册表中拉取或推送。
- Docker Container:Docker映像的运行实例
镜像(image):就类似于“可执行程序”;仓库(Registry)就是用来存储镜像的地方,好比应用商店,公开的仓库有Docker Hub。
- 写完dockerfile交给docker使用build命令编译,那么客户端在接收到请求后转发给docker daemon,接着docker daemon根据dockerfile创建出“可执行程序”image。
- 有了“可执行程序”image后就可以运行程序了,使用命令docker run运行,docker daemon接收到该命令后找到具体的image,然后加载到内存开始执行,image执行起来就是所谓的container。
- docker pull命令就是从Docker Hub中下载image呢。
Docker的安装
一、一行代码解决
# 安装比较旧的版本
sudo apt install docker.io
# 查看docker版本
docker version
# 检测是否成功
sudo docker run hello-world
二、安装新版本的Docker:自己百度
Docker命令
镜像命令
# 展示所有的镜像 参数-a:列出所有;-q:列出id
docker images
# 搜索镜像
docker search mysql
# 下载镜像 不写tag,默认是latest最新版本,分层下载
docker pull mysql
# 指定版本下载
docker pull mysql:5.7
# 删除镜像 参数-f:强制删除
docker rmi -f image_id
docker rmi -f $(docker image -aq)
# 运行镜像 参数 --name="名字",-d:后台运行;-it:交互运行;
docker run [参数] image
例子:docker run -it centos /bin/bash
例子:docker run -d centos 后台运行就必须有一个前台应用,否则会自动停止
容器命令
# 列出当前运行的容器 参数-a:列出所有运行过的容器;-q:列出id
docker ps
# 退出容器
exit
# 删除容器
docker rm 容器id
# 启动和停止容器
docker start 容器id
docker restart 容器id
docker stop 容器id
docker kill 容器id
# 查看容器中的进程
docker top 容器id
# 查看容器的元数据(JSON格式)
docker inspect 容器id
# 进入正在运行的容器
docker exec 容器id # 进入容器并开启一个新的中毒那
docker attach 容器id # 进入容器正在运行的终端,不会创建新的线程
# 拷贝容器内文件出来
docker cp 容器id:/home/test.java /home
小demo实战
部署Nginx
# 1. 搜索镜像
docker search nginx
# 2. 下载镜像
docker pull nginx
# 3. 运行镜像(指定容器名称nginx01,后台运行,-p设置nginx01容器暴露的端口号)
docker run -d --name nginx01 -p 3344:80 nginx
# 4. 本地测试
curl localhost:3344
注意: 修改nginx配置,都需要进入容器内部修改nginx的配置文件,十分麻烦。可以在容器外部提供一个映射路径,在外部修改,内部也自动修改?-v 数据卷
部署tomcat
# 官方的使用
docker run -it --rm tomcat:9.0
# 我们之前的启动都是后台的,停止了容器之后,容器还是可以查到;docker run -it --rm 一般用来测试,用完就删
# 下载
docker pull tomcat
# 启动运行
docker run -d -p 3344:8080 --name tomcat01 tomcat
# 进入容器
docker exec -it tomcat01 /bin/bash
# 发现问题:1.linux命令少了, 2. webapps下内容为空,阿里云认是最小的镜像,所有不必要的都剔除了,保证最小可运行环境即可
访问:http://localhost:3344/
注意: 以后部署项目都要进入容器内部,很麻烦。可以子啊容器外部提供一个映射路径,webapps放置项目,直接自动同步到容器内部。
commit命令
# 提交容器成为一个新的版本,命令和git原理类似
docker commit
例子:
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[TAG]
docker commit -a="gyj" -m="add webapps app" d798a5946c1f tomcat02:1.0
# 详细案例:
# 1. 启动一个默认的tomcat
docker run -d -p 3344:8080 --name tomcat01 tomcat:9.0
# 2. 发现这个默认的tomcat是没有webapps应用,官方镜像默认webapps下面是没有内容的
# 3. 自己拷贝进去了基本的文件
cp -r webapps.dist/* webapps
# 4. 将我们操作过的容器通过commit提交为一个镜像!以后就可以使用我们自己制作的镜像了
docker commit -a="gyj" -m"add webapps" 535d0a4dfa74 tomcat02:1.0
gyj@ubuntu:/$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
tomcat02 1.0 c0913aa43a74 16 seconds ago 467MB
tomcat 9.0 3d0efbe5f648 7 hours ago 462MB
nginx latest 593aee2afb64 6 days ago 187MB
hello-world latest 9c7a54a9a43c 5 months ago 13.3kB
Docker镜像加载原理
联合文件系统
容器数据卷
将应用环境打包成一个镜像!数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化。例如:MySQL,容器删除了,删库跑路!需求:MySQL的数据可以存储在本地。
容器之间可以有一个数据共享的技术!docker容器中产生的数据,同步到本地,这就是卷技术,目录的挂载,将容器内的目录挂载在Linux上面。总结一句话:数据卷就是容器的持久化和同步操作,容器间也是可以数据共享的。
# 使用命令-v来挂载,即:路径映射
docker run -it -v 主机目录:容器目录 image [参数]
例子:docker run -it -v /home/ceshi:/home centos /bin/bash
# 容器启动的时候我们可以通过 docker inspect 容器id 查看容器的元数据(JSON格式)
docker inspect a0c66f548d9f
中间省略
"Mounts": [
{
"Type": "bind",
"Source": "/home/ceshi", # 主机地址
"Destination": "/home", # 容器地址
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
中间省略
具名和匿名挂载
映射的路径可以指定,也可以不指定:
- 指定具体的路径
- 不指定具体的路径:具名和匿名,默认保存在/var/lib/docker/volumes/xxxxxx/_data文件夹里面
# 如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v 容器内路径 # 匿名挂载
-v 卷名:容器内路径 # 具名挂载
-v /主机路径:容器内路径 # 指定路径挂载
# 匿名挂载
docker run -d -P --name nginx01 -v /etc/nginx nginx # -P 随机指定端口
# 具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
# 查看所有volume数据卷的情况
docker volume ls
# 查看某个卷的具体元数据信息
docker volume inspect juming-nginx
[
{
"CreatedAt": "2020-08-12T18:15:21+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", # 挂载的具体目录
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
拓展:
# 通过 -v 容器内容路径 ro rw 改变读写权限
ro readonly # 只读
rw readwrite # 可读可写
# 具名挂载
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:ro nginx
docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内容无法操作
容器之间的数据共享
docker run -d -p 3344:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
# 把mysql02挂载到mysql01上面(父容器)
docker run -d -p 3344:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
DockerFile
很多官方镜像都像是基础包,功能都不完全,我们需要搭建自己的镜像!
构建步骤:
- 编写一个dockerfile文件
- docker build构建为一个镜像
- docker run 运行镜像
- docker push发布镜像(DockerHub、阿里云镜像仓库)
基础知识:
- 每个保留关键字(指令)都是必须大写字母
- 执行从上到下顺序执行
#
表示注释- 每个指令都会创建提交一个新的镜像层,并提交!
DockerFile指令说明
FROM # 基础镜像,一切从这里开始构建
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建build的时候需要运行的命令
ADD # 步骤,tomcat镜像,这个tomcat压缩包!添加内容
WORKDIR # 镜像的工作目录
VOLUME # 挂载的目录
EXPOSE # 保留端口配置
CMD # 容器启动run的时候要运行的命令,只有最后一个会生效可被替代
ENTRYPOINT # 容器启动run的时候要运行的命令,可以追加命令
ONBUILD # 当构建一个被继承DockerFile 这个时候就会运行 ONBUILD 的指令,触发指令
COPY # 类似ADD, 将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量!
案例:创建一个自己的centos
# 1. 编写Dockerfile的文件
vim mydockerfile-centos
cat mydockerfile-centos
FROM centos
MAINTAINER xiaofan<594042358@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH # 镜像的工作目录
RUN yum -y install vim
RUN yum -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "---end---"
CMD /bin/bash
# 2. 通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag] .
docker build -f mydockerfile-centos -t mycentos:1.0 .
# 3. 运行镜像
docker run -it mycentos:1.0 # 不带版本号的话会默认去找最新的
# 补充:列出镜像的构建过程docker history 镜像名称/id
docker history tomcat02:1.0
CMD 和ENTRYPOINT区别
# 1. 编写dockerfile文件
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# vim dockerfile-cmd-test
FROM centos
CMD ["ls", "-a"]
# 2. 构建镜像
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
# 3. run运行, 发现我们的ls -a 命令生效
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# docker run ebe6a52bb125
# 想追加一个命令-l变成ls -al,cmd的情况下-l替换了CMD["ls", "-a"]命令,而-l不是命令
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# docker run ebe6a52bb125 -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"-l\": executable file not found in $PATH": unknown.
# 这个可以成功:ls -al替换了CMD["ls", "-a"],是个完整的命令了
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# docker run ebe6a52bb125 ls -al
# 1. 编写dockerfile文件
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# vim dockerfile-entrypoint-test
FROM centos
ENTRYPOINT ["ls", "-a"]
# 2. 构建文件
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# docker build -f dockerfile-entrypoint-test -t entrypoint-test .
# 3. run运行 发现我们的ls -a 命令同样生效
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# docker run entrypoint-test
# 4. 我们的追加命令, 是直接拼接到ENTRYPOINT命令的后面的!
[root@iZ2zeg4ytp0whqtmxbsqiiZ dockerfile]# docker run entrypoint-test -l
实战:Tomcat镜像
自己的镜像要求:tomcat压缩包 , jdk的压缩包,事先放在文件夹里面
# 1. 编写Dockerfile文件,官方命名Dockerfile, build会自动寻找这个文件,就不需要-f指定
cat Dockerfile
FROM centos
MAINTAINER xiaofan<594042358@qq.com>
COPY readme.txt /usr/local/readme.txt
ADD jdk-8u73-linux-x64.tar.gz /usr/local/
ADD apache-tomcat-9.0.37.tar.gz /usr/local/
RUN yum -y install vim
ENV MYPATH /usr/local
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_73
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.37
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.37
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080
CMD /usr/local/apache-tomcat-9.0.37/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.37/bin/logs/catalina.out
# 2. 构建镜像(docker build -t 镜像名字 位置)
docker build -t diytomcat .
# 3. 启动镜像(两个文件夹的挂载)
docker run -d -p 3344:8080 --name gyj-tomcat1
-v /home/gyj/build/tomcat/test:/usr/local/apache-tomcat-9.0.37/webapps/test
-v /home/gyj/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.37/logs diytomcat
# 4. 本地目录创建web.xml和index.jsp文件进行测试
http://localhost:3344/test/
SpringBoot项目打包
- 构建springboot项目并打包jar包
- 编写Dockerfile
FROM openjdk:8
COPY *.jar /app.jar
CMD ["--server.port=8080"]
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
- 上传jar包和Dockerfile文件到服务器目录
- 构建镜像,运行
# 构建镜像image名称为:testlinux01
docker build -t testlinux01 .
# 运行镜像(随机分配端口)
docker run -d -P --name testlinux testlinux01
# 访问
http://localhost:49154/kaikai
镜像发布
把创建好的镜像发布到DockerHub:
# 1. 发布到hub.docker.com仓库,首先登录
docker login -u gongyongjie
# 2. 打标签,确定要推送的镜像标签
# docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
docker tag tomcat02:1.0 gongyongjie/tomcat02:1.0
# 3. 推送Docker镜像到指定仓库docker push NAME[:TAG]
docker push gongyongjie/tomcat02:1.0
# The push refers to repository [docker.io/gongyongjie/tomcat02]
把创建好的镜像发布到阿里云:
# 1. 登录阿里云,找到容器镜像服务
# 2. 创建命名空间和镜像仓库
# 以下参考官方文档即可
# 3. 登录
docker login --username=gyj1515895859 registry.cn-qingdao.aliyuncs.com
# 4. 将镜像推送到Registry
docker login --username=gyj1515895859 registry.cn-qingdao.aliyuncs.com
docker tag [ImageId] registry.cn-qingdao.aliyuncs.com/gongyongjie/test-docker:[镜像版本号]
docker push registry.cn-qingdao.aliyuncs.com/gongyongjie/test-docker:[镜像版本号]
# 5. 从Registry中拉取镜像
docker pull registry.cn-qingdao.aliyuncs.com/gongyongjie/test-docker:[镜像版本号]
小结
(未完待续~~~~~)