Docker概述
Docker为什么出现
一款产品: 开发–上线 两套环境!应用环境,应用配置!
开发 — 运维。 问题:我在我的电脑上可以允许!版本更新,导致服务不可用!对于运维来说考验十分大?
环境配置是十分的麻烦,每一个及其都要部署环境(集群Redis、ES、Hadoop…) !费事费力。
发布一个项目( jar + (Redis MySQL JDK ES) ),项目能不能带上环境安装打包!
之前在服务器配置一个应用的环境 Redis MySQL JDK ES Hadoop 配置超麻烦了,不能够跨平台。
开发环境Windows,最后发布到Linux!
传统:开发jar,运维来做!
现在:开发打包部署上线,一套流程做完!
安卓流程:java — apk —发布(应用商店)一 张三使用apk一安装即可用!
docker流程: java-jar(环境) — 打包项目帯上环境(镜像) — ( Docker仓库:商店)-----运维下载我们发布的镜像---直接运行即可!
Docker给以上的问题,提出了解决方案!

Docker的思想就来自于集装箱!
JRE – 多个应用(端口冲突) – 原来都是交叉的! 隔离:Docker核心思想!打包装箱!每个箱子是互相隔离的。
Docker通过隔离机制,可以将服务器利用到极致!
本质:所有的技术都是因为出现了一些问题,我们需要去解决,才去学习!
Docker历史
2010年,几个的年轻人,就在美国成立了一家公司 dotcloud
做一些pass的云计算服务!LXC(Linux Container容器)有关的容器技术!
Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源。
他们将自己的技术(容器化技术)命名就是 Docker Docker刚刚延生的时候,没有引起行业的注意!dotCloud,就活不下去!
开源
2013年,Docker开源!
越来越多的人发现docker的优点!火了。Docker每个月都会更新一个版本!
2014年4月9日,Docker1.0发布!
docker为什么这么火?十分的轻巧!
在容器技术出来之前,我们都是使用虚拟机技术!
虚拟机:在window中装一个VMware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重!
虚拟机也属于虚拟化技术,Docker容器技术,也是一种虚拟化技术!
Docker基于Go语言开发的!开源项目!
docker官网:https://www.docker.com/
文档:https://docs.docker.com/ Docker的文档是超级详细的!
Docker能干嘛
之前的虚拟机技术

虚拟机技术缺点:
1、 资源占用十分多
2、 冗余步骤多
3、 启动很慢!
容器化技术
容器化技术不是模拟一个完整的操作系统

比较Docker和虚拟机技术的不同:
- 传统虚拟机,虚拟出一条硬件,运行一个完整的操作系统,然后在这个系统上安装和运行软件
- 容器内的应用直接运行在宿主机的内容,容器是没有自己的内核的,也没有虚拟我们的硬件,所以就轻便了
- 每个容器间是互相隔离,每个容器内都有一个属于自己的文件系统,互不影响
DevOps(开发、运维)
应用更快速的交付和部署
传统:一对帮助文档,安装程序。
Docker:打包镜像发布测试一键运行。
更便捷的升级和扩缩容
使用了 Docker之后,我们部署应用就和搭积木一样 项目打包为一个镜像,扩展服务器A!服务器B更简单的系统运维 在容器化之后,我们的开发,测试环境都是高度一致的
更高效的计算资源利用
Docker是内核级别的虚拟化,可以在一个物理机上可以运行很多的容器实例!服务器的性能可以被压榨到极致。
Docker基本操作
Docker的基本组成

镜像(image):
docker镜像就好比是一个目标,可以通过这个目标来创建容器服务,tomcat镜像>run>容器(提供服务器),通过这个镜像可以创建多个容器(最终服务运行或者项目运行就是在容器中的)。
容器(container):
Docker利用容器技术,独立运行一个或者一组应用,通过镜像来创建的. 启动,停止,删除,基本命令 目前就可以把这个容器理解为就是一个简易的 Linux系统。
仓库(repository):
仓库就是存放镜像的地方! 仓库分为公有仓库和私有仓库。(很类似git) Docker Hub是国外的。 阿里云…都有容器服务器(配置镜像加速!)
安装Docker
环境查看
#Linux要求内核3.0以上
[root@yuan ~]# uname -r
3. 10.0-1127.19.1.el7.x86_64
#系统版本
[root@yuan ~]# 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"
安装
帮助文档:https://docs.docker.com/engine/install/
#1.卸载旧版本
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
#2.需要的安装包
yum install -y yum-utils
#3.设置镜像仓库
yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
#上述方法默认是从国外的,不推荐
#推荐使用国内的
yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #阿里云镜像,速度快
#更新yum软件包索引
yum makecache fast
#4.安装docker相关的 docker-ce 社区版 而ee是企业版
yum install docker-ce docker-ce-cli containerd.io #安装社区版即可
#或者指定安装的版本
yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
#6.启动Docker
systemctl start docker
#6. 使用docker version查看是否按照成功
docker version

7. 测试
docker run hello-world

#8.查看已经下载的镜像(从这里可以查看已有镜像的)
docker images

卸载Docker
#1. 卸载依赖
yum remove docker-ce docker-ce-cli containerd.io
#2. 删除资源
rm -rf /var/lib/docker
# /var/lib/docker 是docker的默认工作路径!
阿里云镜像加速
- 登录阿里云,找到容器镜像服务

- 找到镜像加上地址

- 配置使用
#创建目录
sudo mkdir -p /etc/docker
#编写配置文件
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://l259soi6.mirror.aliyuncs.com"]
}
EOF
#重启
sudo systemctl daemon-reload
#启动
sudo systemctl restart docker

Run的流程和Docker的原理

docker run 流程图

Docker的原理
Docker是怎么工作的?
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上。通过Socket从客户端访问!
Docker-Server接收到Docker-Client的指令,就会执行这个命令!

为什么Docker比Vm快
1、docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。 2、docker利用的是宿主机的内核,而不需要Guest OS。

因此,当新建一个 容器时**,docker不需要和虚拟机一样重新加载一个操作系统内核**。仍而避免引导、加载操作系统内核返个比较费时费资源的过程,当新建一个虚拟机时,虚拟机软件需要加载GuestOS,返个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了这个复杂的过程,因此新建一个docker容器只需要几秒钟。
Docker镜像的基本命令
帮助命令
docker version #显示docker的版本信息。
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令
帮助文档的地址:https://docs.docker.com/engine/reference/commandline/build/
docker images查看所有本地的主机上的镜像
[root@yuan ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest feb5d9fea6a5 5 months ago 13.3kB
#解释
REPOSITORY 镜像的仓库源
TAF 镜像的标签
IMAGE ID 镜像的ID
CREATED 镜像的创建时间
SIZE 镜像的大小
#可选项
-a #列出所有镜像
-q #显示镜像的id
docker images --help,查看可选参数
docker search mysql,搜索镜像
也可以在搜索帮助文档:https://hub.docker.com/
[root@yuan ~]# docker search mysql #搜索镜像为mysql
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql/mysql-server Optimized MySQL Server Docker images. Create… 906 [OK]
# --filter=STARS=3000 #过滤,搜索出来的镜像收藏STARS数量大于3000的
[root@yuan ~]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
docker search images --help,查看可选参数
docker pull:下载镜像
# 下载镜像 docker pull 镜像名[:tag]
[root@yuan ~]# docker pull mysql
Using default tag: latest #如果不写tag,默认就是latest,下载最新的
latest: Pulling from library/mysql
72a69066d2fe: Pull complete #分层下载: docker image 的核心 联合文件系统
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709 # 签名防伪
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest #真实地址
#指定版本下载
[root@yuan ~]# docker pull mysql:5.7 #指定mysql版本为5.7
5. 7: Pulling from library/mysql
72a69066d2fe: Already exists
93619dbc5b36: Already exists
99da31dd6142: Already exists
626033c43d70: Already exists
37d5d7efb64e: Already exists
ac563158d721: Already exists
d2ba16033dad: Already exists
0ceb82207cd7: Pull complete
37f2405cae96: Pull complete
e2482e017e53: Pull complete
70deed891d42: Pull complete
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Downloaded newer image for mysql:5.7
docker.io/library/mysql:5.7
docker pull images --help,查看可选参数
docker rmi 删除镜像
[root@yuan /]# docker rmi -f容器id #删除指定的容器
[root@yuan /]# docker rmi -f 容器id 容器id 容器id 容器id #删除多个容器
[root@yuan /]# docker rmi -f $(docker images -aq) #删除全部的容器
Docker容器的命令
说明:我们有了镜像才可以创建容器,Linux,下载centos镜像来学习
镜像下载
#docker中下载centos
docker pull centos
docker run [可选参数]
#参数说明
--name="Name" 容器名字tomcat01 tomcat02,用来区分容器
-d 后台方式运行
-it 使用交互方式运行,进入容器查看内容
-p(小写) 指定容器的端口 -p 8080:8080
-p ip:主机端口:容器端口
-p主机端口:容器端口(常用)
-p容器端口 -p的4种方式
-P(大小) 随机指定端口
#测试,启动并进入容器
[root@yuan ~]# docker run -it centos /bin/bash
[root@084596d7c0d3 /]# ls #查看容器内的sentos
bin etc lib lost+found mnt proc run srv tmp var
dev home lib64 media opt root sbin sys usr
[root@084596d7c0d3 /]# exit #从容器中返回主机
exit
[root@yuan ~]# ls /
bin dev home lib64 media opt proc run srv test1 usr www
boot etc lib lost+found mnt patch root sbin sys tmp var
[root@yuan ~]#
列出所有运行的容器
# docker ps命令
#列出当前正在运行的容器
-a #列出当前正在运行的容器+带出历史运行过的容器
-n=? #显示最近创建的容器
-q #显示容器的编号
[root@yuan ~]# docker ps #列出当前正在运行的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@yuan ~]# docker ps -a #列出当前正在运行的容器+带出历史运行过的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
084596d7c0d3 centos "/bin/bash" 7 minutes ago Exited (0) 5 minutes ago wonderful_darwin
328f96b56bdb hello-world "/hello" 7 hours ago Exited (0) 7 hours ago musing_ellis
aac537812f96 hello-world "/hello" 2 weeks ago Exited (0) 2 weeks ago wonderful_lamport
[root@yuan ~]# docker ps -a -n=1 #显示最近创建1的容器
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
084596d7c0d3 centos "/bin/bash" 7 minutes ago Exited (0) 5 minutes ago wonderful_darwin
[root@yuan ~]# docker ps -a -q #显示所有容器的编号
084596d7c0d3
328f96b56bdb
aac537812f96
exit #直接容器停止并退出
ctrl +P+Q # 容不停止退出
删除容器
#删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -rf
docker rmi -f 容器id
#杀死运行的容器:
docker kill $(docker ps -a -q)
#删除所有容器:
docker rm $(docker ps -a -q)
#强制删除所有镜像:
docker rmi -f $(docker images -q)
#docker删除所有停止的容器
docker rm $(sudo docker ps -a -q)
启动和停止容器的操作
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
其它基本命令
后台启动命令
#命令 docker run -d 镜像名
[root@yuan ~]# docker run -d centos
#doccker 使用后台运行,就必须要有一个前提运行进程,docker没用发现应用,就会自动停止
#nginx:容器启动后,发现没用提供服务,就会立刻停止,就没有进程了
查看日志
#自己编写一段shlle脚本
[root@yuan ~]# docker run -d centos /bin/sh -c "while true;do echo yuan;sleep 1;done"
2b9769fa265843bddad852c2a5effb3ca208fd4cee116ef41427a81f0c160de1
[root@yuan ~]# docker ps #查看centos是否在后台运行
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b9769fa2658 centos "/bin/sh -c 'while t…" 7 seconds ago Up 6 seconds pedantic_mayer
#显示日志
-tf #显示日志
--tail number #要显示日志条数
[root@yuan ~]# docker logs -tf --tail 10 2b9769fa2658 #查看centos的前10条日志
2022-02-23T01:22:01.676927165Z yuan
2022-02-23T01:22:02.683064380Z yuan
2022-02-23T01:22:03.684921592Z yuan
2022-02-23T01:22:04.687020821Z yuan
2022-02-23T01:22:05.689034931Z yuan
2022-02-23T01:22:06.691270963Z yuan
2022-02-23T01:22:07.693456263Z yuan
2022-02-23T01:22:08.695734978Z yuan
2022-02-23T01:22:09.698152340Z yuan
2022-02-23T01:22:10.700539806Z yuan
2022-02-23T01:22:11.735604439Z yuan
查看容器中的进程信息
#查看容器的进程信息
docker top 容器id
#测试
[root@yuan ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b9769fa2658 centos "/bin/sh -c 'while t…" 8 minutes ago Up 8 minutes pedantic_mayer
[root@yuan ~]# docker top 2b9769fa2658 #查看容器的进程信息
UID PID PPID C STIME TTY TIME CMD
root 7029 7009 0 09:21 ? 00:00:00 /bin/sh -c while true;do echo yuan;sleep 1;done
root 8525 7029 0 09:30 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 1
[root@yuan ~]#
查看镜像的元数据
#命令
docker inspect 容器id
#测试
[root@yuan ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b9769fa2658 centos "/bin/sh -c 'while t…" 34 minutes ago Up 34 minutes pedantic_mayer
[root@yuan ~]# docker inspect 2b9769fa2658
[
{
"Id": "2b9769fa265843bddad852c2a5effb3ca208fd4cee116ef41427a81f0c160de1",
"Created": "2022-02-23T01:21:31.272695941Z",
"Path": "/bin/sh",
......
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02",
"DriverOpts": null
}
}
}
}
]
进入容器的拷贝命令
#容器 通常是后台的方式运行的
#命令
docker exec -it 容器id baseShell
#测试方式一
[root@yuan ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2b9769fa2658 centos "/bin/sh -c 'while t…" 45 minutes ago Up 45 minutes pedantic_mayer
[root@yuan ~]# docker exec -it 2b9769fa2658 /bin/bash #进入容器contos
[root@2b9769fa2658 /]# ls -a
. .dockerenv dev home lib64 media opt root sbin sys usr
.. bin etc lib lost+found mnt proc run srv tmp var
[root@2b9769fa2658 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 01:21 ? 00:00:01 /bin/sh -c while true;do echo yuan;sleep 1;done
root 2748 0 0 02:07 pts/0 00:00:00 /bin/bash
root 2787 1 0 02:07 ? 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr
root 2788 2748 0 02:07 pts/0 00:00:00 ps -ef
[root@2b9769fa2658 /]#
#方式二
docker attach 容器id
#测试
[root@yuan ~]# docker attach 2b9769fa2658
正在执行的当前的代码....
两者的区别
# docker exec #进入容器后开启一个新的终端,可以在里面操作(常用)
# docker attach #进入容器正在执行的终端,不会启动新的进程
从容器内拷贝文件到主机上
docker cp 容器id:容器内路径 目的的主机路径
#测试
[root@yuan home]# ls -a
. .. redis www yuan
[root@yuan home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
980d85c0ab6b centos "/bin/bash" 18 minutes ago Up 18 minutes sharp_saha
#进入容器内
[root@yuan home]# docker attach 980d85c0ab6b
[root@980d85c0ab6b /]# cd home
[root@980d85c0ab6b home]# ls -a
. ..
#在容器的home目录下新建一个文件
[root@980d85c0ab6b home]# touch test.java
[root@980d85c0ab6b home]# ls -a
. .. test.java
[root@980d85c0ab6b home]# exit
exit
[root@yuan home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
#将容器内的test.java复制到到主机中
[root@yuan home]# docker cp 980d85c0ab6b:/home/test.java /home
[root@yuan home]# ls -a
. .. redis test.java www yuan
[root@yuan home]#
基本命令小结

命令大全
attach Attach local standard input, output, and error streams to a running container
#当前shell下 attach连接指定运行的镜像
build Build an image from a Dockerfile # 通过Dockerfile定制镜像
commit Create a new image from a container changes #提交当前容器为新的镜像
cp Copy files/folders between a container and the local filesystem #从容器中拷贝到指定文件或目录到主机中
create Create a new container #创建一个新的容器
diff Inspect changes to files or directories on a container's filesystem #查看docker容器的变化
events Get real time events from the server # 从服务获取容器实时时间
exec Run a command in a running container # 在运行中的容器上运行命令
export Export a container's filesystem as a tar archive #导出容器文件系统作为一个tar归档文件[对应import]
history Show the history of an image # 展示一个镜像形成历史
images List images #列出系统当前的镜像
import Import the contents from a tarball to create a filesystem image #从tar包中导入内容创建一个文件系统镜像
info Display system-wide information # 显示全系统信息
inspect Return low-level information on Docker objects #查看容器详细信息
kill Kill one or more running containers # kill指定docker容器
load Load an image from a tar archive or STDIN #从一个tar包或标准输入中加载一个镜像[对应save]
login Log in to a Docker registry #注册或者登录一个docker源服务器
logout Log out from a Docker registry #从当前docker退出
logs Fetch the logs of a container #输出当前容器的信息
pause Pause all processes within one or more containers #暂停容器
port List port mappings or a specific mapping for the container #查看映射端口对应的容器内部源端
ps List containers #列出容器列表
pull Pull an image or a repository from a registry #从docker镜像源服务器拉取指定镜像或者库镜像
push Push an image or a repository to a registry #推送指定镜像或库镜像至docker源服务器
rename Rename a container
restart Restart one or more containers #重启运行的容器
rm Remove one or more containers #移除一个或者多个容器
rmi Remove one or more images #移除一个或多个镜像【无容器使用改镜像才可删除,否则需要删除相关内容器才可继续或 -f强制删除】
run Run a command in a new container #创建一个新的内容并运行一个命令
save Save one or more images to a tar archive (streamed to STDOUT by default) #保存一个镜像为一个tar包【对应 load】
search Search the Docker Hub for images #在docker hub 中搜索镜像
start Start one or more stopped containers #启动容器
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers #停止容器
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE #给源中的镜像打标签
top Display the running processes of a container #查看容器中的进程信息
unpause Unpause all processes within one or more containers #取消暂定的容器
update Update configuration of one or more containers
version Show the Docker version information #查看docker版本号
wait Block until one or more containers stop, then print their exit codes #截取容器停止的退出状态值
部署Nginx
#1.搜索镜像
[root@yuan ~]# docker search nginx
#2.拉取镜像
[root@yuan ~]# docker pull nginx
#3.查看镜像
[root@yuan ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.0.28 17b062d639f4 5 days ago 519MB
nginx latest 605c77e624dd 7 weeks ago 141MB
#4.启动运行
# -d 后台运行
# --name 给容器起名字
# -p 宿主机端口:容器内部端口 宝塔和阿里云需要开启3344端口
#不指定名称:docker run -d -p 3344:90 nginx
[root@yuan ~]# docker run -d --name nginx02 -p 3344:90 nginx
c6c57c393e08a1a6dea111540ef7d8022637cff1ec7734622733c5e8070316c3
#5.查看运行状态
[root@yuan ~]# docker ps
CONTAINER ID IMAGE COMMAND
c6c57c393e08 nginx "/docker-entrypoint.…"
#5.本机自测运行情况
[root@yuan ~]# curl localhost:3344
<!DOCTYPE html>
<html>
......
</body>
</html>
#进入配置
[root@yuan ~]# docker exec -it nginx02 /bin/bash
root@83953c538f77:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@83953c538f77:/# cd /etc/nginx
root@83953c538f77:/etc/nginx# ls
conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params
root@83953c538f77:/etc/nginx# exit
exit
#停止nginx
[root@yuan ~]# docker ps
CONTAINER ID IMAGE COMMAND
83953c538f77 nginx "/docker-entrypoint.…"
[root@yuan ~]# docker stop 83953c538f77
83953c538f77
[root@yuan ~]#

部署Tomcat
# 官网推荐的安装方式:之前的启动都是后台,停止了容器,容器还是可以查到, docker run -it --rm 镜像名 一般是用来测试,用完就删除
[root@yuan ~]# docker run -it --rm tomcat:9.0
#安装tomcat最新版本的 docker pull tomcat:9.0 指定版本为9.0
[root@yuan ~]# docker pull tomcat
#查看镜像是否下载
[root@yuan ~]# docker images
#以后台方式,暴露端口方式,启动运行
# -d 后台运行
# --name 给容器起名字
# -p 宿主机端口:容器内部端口 宝塔和阿里云需要开启3355端口
#不指定名称:docker run -d -p 3355:8080 tomcat
docker run -d -p 3355:8080 --name tomcat01 tomcat
#查看运行状态
[root@yuan ~]# docker ps
CONTAINER ID IMAGE
5fb35759e29e tomcat
#本机自测运行情况404
#浏览器访问:http://宝塔公网id:3355/
[root@yuan ~]# curl localhost:3355
<!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style typ
#根据容器名称:tomcat01或id进入tomcat容器
[root@yuan ~]# docker exec -it tomcat01 /bin/bash
root@5fb35759e29e:/usr/local/tomcat# ls -l #查看tomcat容器内部内容:
total 160
-rw-r--r-- 1 root root 18994 Dec 2 22:01 BUILDING.txt
-rw-r--r-- 1 root root 6210 Dec 2 22:01 CONTRIBUTING.md
-rw-r--r-- 1 root root 60269 Dec 2 22:01 LICENSE
-rw-r--r-- 1 root root 2333 Dec 2 22:01 NOTICE
-rw-r--r-- 1 root root 3378 Dec 2 22:01 README.md
-rw-r--r-- 1 root root 6905 Dec 2 22:01 RELEASE-NOTES
-rw-r--r-- 1 root root 16517 Dec 2 22:01 RUNNING.txt
drwxr-xr-x 2 root root 4096 Dec 22 17:07 bin
drwxr-xr-x 1 root root 4096 Feb 24 09:30 conf
drwxr-xr-x 2 root root 4096 Dec 22 17:06 lib
drwxrwxrwx 1 root root 4096 Feb 24 09:30 logs
drwxr-xr-x 2 root root 4096 Dec 22 17:07 native-jni-lib
drwxrwxrwx 2 root root 4096 Dec 22 17:06 temp
drwxr-xr-x 2 root root 4096 Dec 22 17:06 webapps
drwxr-xr-x 7 root root 4096 Dec 2 22:01 webapps.dist
drwxrwxrwx 2 root root 4096 Dec 2 22:01 work
root@5fb35759e29e:/usr/local/tomcat# cd webapps
# 发现问题:1、linux命令少了。 2.webapps目录为空
# 原因:阿里云镜像的原因,阿里云默认是最小的镜像,所以不必要的都剔除掉
# 保证最小可运行的环境!
# 解决方案:
# 将webapps.dist下的文件都拷贝到webapps下即可
root@5fb35759e29e:/usr/local/tomcat/webapps# ls
root@5fb35759e29e:/usr/local/tomcat/webapps# cd ..
root@5fb35759e29e:/usr/local/tomcat# cp -r webapps.dist/* webapps #找到webapps.dist复制webapps下即可
root@5fb35759e29e:/usr/local/tomcat# cd webapps #进入webapps
root@5fb35759e29e:/usr/local/tomcat/webapps# ls #查看拷贝结果
ROOT docs examples host-manager manager
root@5fb35759e29e:/usr/local/tomcat/webapps#
#停止tomcat
[root@yuan ~]# docker stop 5fb35759e29e
5fb35759e29e

部署部署elasticsearch+kibana
# es 暴露的端口很多!
# es 十分耗内存
# es 的数据一般需要放置到安全目录!挂载
# --net somenetwork ? 网络配置
#docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag
#安装并启动es,7.6.2版本
[root@yuan ~]# docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:7.6.2
# 测试一下es是否成功启动
[root@yuan ~]# curl localhost:9200
{
"name" : "2e7ddb9e066b",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "zq6j-OEESFuxAldeoqFWLw",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
# 查看docker容器使用内存情况
[root@yuan ~]# docker stats

#测试成功就关掉elasticSearch,可以添加内存的限制,修改配置文件 -e 环境配置修改 -Xms64m:指定64MB -Xmx512m:最大512MB
docker run -d --name elasticsearch02 -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
# 查看docker容器使用内存情况
[root@yuan ~]# docker stats

#测试
[root@yuan ~]# curl localhost:9200
{
"name" : "f02416879a5a",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "cuVPjNkCQ72pdlDPv-Q1pg",
"version" : {
"number" : "7.6.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "ef48eb35cf30adf4db14086e8aabd07ef6fb113f",
"build_date" : "2020-03-26T06:34:37.794943Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
Portainer 可视化面板安装
# 安装命令
docker run -d -p 8081:9000 \
--restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
测试外网访问:测试访问: 外网:8081 :http://外网Ip地址:8081/

登录成功

Docker镜像理解
Docker镜像
镜像是什么
镜像是一种轻量级、可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码、运行时、库、环境变量和配置文件。
所有的应用,直接打包docker镜像,就可以直接跑起来
如何得到镜像:
- 从远处仓库下载
- 朋友拷贝给你
- 自己制作一个镜像DockerFile
UnionFS(联合文件系统)
UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。
镜像加载原理
**bootfs(boot file system)**主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。
rootfs (root file system),在bootfs之上。包含的就是典型 Linux 系统中的 /dev,/proc,/bin,/etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

平时我们安装虚拟机的centos都是好几个G,为什么Docker这里才200M?

对于一个精简的OS,rootfs 可以很小,只需要包含最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的linux发行版, bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs。
虚拟机是分钟级别的,容器是秒级别的。
分层的镜像
我们去下载一个镜像,注意观察下载的日志输出,可以看到是一层一层的在下载!

最大的好处,我觉得莫过于是资源共享了,比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需要在磁盘上保留一份base镜像,同时内存中只需要加载一份base镜像,这样就可以为多有的容器服务了,而且每一层都可以被共享
查看镜像分层的方式可以通过docker image inspect 命令
[root@localhost ~]# docker image inspect redis:latest
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:7e718b9c0c8c2e6420fe9c4d1d551088e314fe923dce4b2caf75891d82fb227d",
"sha256:89ce1a07a7e4574d724ea605b4877f8a73542cf6abd3c8cbbd2668d911fa5353",
"sha256:9eef6e3cc2937e452b2325b227ca28120a70481be25404ed9aad27fa81219fd0",
"sha256:ee748697d275b904f1d5604345d70b647a8c145b9f05aeb5ca667e1f256e43d8",
"sha256:f1f7964d40afa49c6ef63ab11af91044e518a2539f567783ce997d3cea9ce8f6",
"sha256:3d9fda8ff875e549d54e9d7504ce17d27423fe27dafbb92127c603dddad7fa13"
]
},
理解:
所有的 Docker|镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux 16.04 创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
该镜像当前已经包含 3 个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

在添加额外的镜像层的同时,镜像始终是保持当前所有镜像的组合,理解这一点是非常重要的。下图拒了一个简单的例子,每个镜像包含三个文件,而镜像包含了来自两个镜像层的6个文件。

上图中的镜像层和之前的图中略有区别,主要目的是便于展示文件
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层的文件7是文件5的一个更新版

这种情况下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。 Docker 通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系統。 Linux 上可用的存储引擎有 AUFS、Overlay2、Device Mapper、Btrfs 以及 ZFS。顾名思义,每种存储引擎都基于 Linux 中对应的文件系统或者块设备技术,并且每种存储引擎都有其独有的性能特点。
Docker 在 Windows 上仅支持 windowsfiter一种存储引擎,该引擎基于 NTFS 文件系统之上实现了分层和 CoW[1]。
下图展示了与系统显示相同的三层镜像。所有镜像层堆叠并合井,对外提供统一的视图。
特点
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像顶部!
这一层就是我们通常说的容器层,容器之下的都叫镜像层

Commit镜像
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="提交的描述信息" -a="作者" 容器id 目标镜像名:[tag]
实战
#1、启动一个默认的tomcat
# 2、发现这个默认的tomcat是没有webapps应用,镜像的原因,官方的镜像默认webapps下面是没有文件的!
#3、拷贝进去了基本的文件,或者把webapps.dist拷贝到webapps
#4、将我们操作过的容器通过commit提交为一个镜像!我们以后就使用我们修改过的镜像即可,这就是我们自己的一个修改的镜像
[root@yuan ~]# docker commit -a="yuan" -m="add webapps app" f9e8dc883d5d tomcat02:1.0
sha256:992cf51e07e12a87e4a50e81065fbd5cc83d256ea7b707299a298579967a257e

如果你想要保存当前的状态,就通过commit提交,获得一个镜像,就好比我们以前学习VM时候,快照
容器数据卷
容器数据卷
将应用环境打包成一个镜像!
数据?如果数据都在容器中,那么我们容器删除,数据就会丢失!需求:数据可以持久化
MySQL,容器删除了,删库跑路!需求:MySQL的数据可以存储在本地
容器之间可以有一个数据共享的技术!docker容器中产生的数据,同步到本地
这就是卷技术,目录的挂载,将容器内的目录挂载在Linux上面

总结一句话:容器的持久化和同步操作,容器间也是可以数据共享的
使用数据卷,直接使用命令挂载 -v
docker run -it -v 主机目录:容器内目录 -p 主机端口:容器内端口
#测试
# /home/ceshi:主机home目录下的ceshi文件夹 映射:centos容器中的/home /bin/bash:进入容器内
[root@yuan home]# docker run -it -v /home/ceshi:/home centos /bin/bash
#查看目录是否挂载
[root@yuan ~]# docker ps
#新开一个窗口,通过 docker inspect 容器id 查看
[root@yuan ~]# docker inspect c638b856d427

测试文件同步

1、停止容器
2、宿主机修改文件
3、启动容器
4、容器内的数据依旧是同步的
#通过该命令查看关闭的centos选择第一个
[root@yuan home]# docker ps -a


Mysql数据同步
# 获取mysql镜像,如果存在则不需要下载
[root@yuan home]# docker pull mysql:8.0.28
# 运行容器,需要做数据挂载 #安装启动mysql,需要配置密码的
# 参考官网hub :docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#测试
#注:在远程需要开启3310端口,阿里云
-d 后台运行
-p 端口映射
-v 卷挂载,可以挂载多个
-e 环境配置
-- name 容器名字
[root@yuan home]# docker run -d -p 3310:3306 -v /home/mysql/conf:/etc/mysql/conf.d -v /home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql03 mysql:8.0.28
3a7d840bfa16a5c4881896d8030d9c2354be9bc7f08056913be72780ee702a6a
# 启动成功之后,我们在本地使用Navicat 来测试一下
# Navicat-连接到服务器的3310--和容器内的3306映射

在本地用Navicat新建名称为test的数据库时候,容器容器也会创建

假设我们将包含mysql的容器删除时,本机也会存在

我们挂载到本地的数据卷依旧没有丢失,这就实现了容器数据持久化功能。
具名和匿名挂载
#匿名挂载
-v 容器内路径
-P 大P随机端口
#如果发现nginx01创建不了,可以删除以前创建的即可
[root@yuan ~]# docker rm -f nginx01
[root@yuan ~]# docker run -d -P --name nginx01 -v /ect/nginx nginx
#查看所有的volume的情况
[root@yuan ~]# docker volume ls
DRIVER VOLUME NAME
local 86ab6a63b1617157876c89c732aec16a1a94cfb4777b1aec1990d913acc061fb
#这种就是匿名挂载,-v写的是容器内的路径,没有写容器外的路径
#具名挂载
[root@yuan ~]# docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
49194ece7439bc26e8f845c1efeee8f36c3229a404b5b5973276f0971364fa60
[root@yuan ~]# docker volume ls
DRIVER VOLUME NAME
local b159b2a9a87b452b4d35c715e83233b8210dc7ddc1d7ea9441ab87bffb9cdb5a
local juming-nginx

所有docker容器内的卷,没有指定目录的情况下在/var/bib/docker/volumes/XXXX/_data

我们通过具名挂载可以方便的找到我们的一个卷,大多数情况在使用的具名挂载
#如何确定是具名挂载还是匿名挂载,还是指定路径挂载!
-v容器内路径 #匿名挂载
-v卷名:容器内路径 #具名挂载
-v /宿主机路径::容器内路径 #指定路径挂载!
拓展
# 通过 -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就说明这个路径只能通过宿主机来操作,容器内部是无法进行操作的
数据卷之DockerFile初始
在home新建以目录为docker-test-volume,在该目录下使用vim编辑器 vim dockerfile1输入一些内容
#创建一个dockerfile文件,建议为dockerfile
#文件中的内 指令(大小) 参数
FROM centos
VOLUME ["volume01"."volume02"] #匿名挂载
CMD echo "----end----"
cmd /bin/bash
#这里每个命令就是镜像的一层
执行该命令
#注:
#/home/docker-test-volume/dockerfile1:文件目录
#yuan/centos:1.0:自定义镜像名
#后面必须加点 .
[root@yuan docker-test-volume]# docker build -f /home/docker-test-volume/dockerfile1 -t yuan/centos:1.0 .


启动自己写的容器

查看一下卷挂载的路径
[root@yuan ~]# docker inspect 1ac68659a54a

发现新建的文件已同步


这种方式未来的使用非常多,因为我们自己通常会构建自己的镜像
假设构建镜像的时候没有挂载,需要自己手动挂载镜像 -v 卷名:容器内路径
多个数据进行同步DockerFile初始

启动3个容器,通过我们刚在自己写的镜像启动*


在一个数据卷中新建一个文件,发现docker01的数据同步到了docker02


# 测试 :可以删除容器dcoker01,查看docker02和docker03时候还可以访问这个文件
# 测试结果是依然可以访问到

多个MySQL实现数据共享
docker run -d -p 3310:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:8.0.27
docker run -d -p 3311:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:8.0.27
# 这个时候可以实现两个容器数据同步
结论:
容器之间配置信息的传递,数据卷容器的生命周期这一直持续到没有容器使用为止
但是一旦持久化到了本地,这个时候,本地的数据不会被删除
Dockerfile
DockerFile介绍
构建步骤:
1、编写一个dockerfile文件
2、docker build构建为一个镜像
3、docker run 运行镜像
4、docker push发布镜像(DockerHub、阿里云镜像仓库)

Docker Hub中99%的镜像都是从这个基础镜像过来的FROM scratch,然后配置需要的软件和配置来进行构建的

很多官方的镜像都是基础包,很多功能都没有,我们通常会自己搭建自己的镜像
官方可以制作镜像,那我们也可以
DockerFile镜像的构建
基础知识:
1、每个保留关键字(指令)都是必须是大写字母
2、执行从上到下顺序执行
3、#表示注释
4、每一个指令都会创建提交一个新的镜像层,并提交

dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件,这个文件十分简单!
Docker镜像逐渐成为了企业交付的标准,必须要掌握
步骤:开发,部署,运维…缺一不可
DockerFile:构建文件,定义了一切的步骤,源代码
DockerImages:通过DockerFile构建生成的镜像,最终发布和运行的产品
Docker容器:容器就是镜像运行起来提供服务的
Docker指令
FROM # 基础镜像,一切从这里开始
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat镜像,这个tomcat压缩包,添加内容
WORKDIR # 镜像的工作目录
VOLUME #挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定容器运行时的shell命令,只有最后一个生效,可被替代
ENTRYPOINT # 指定容器运行时的shell命令,可以追加命令
ONBUILD # 当构建一个被继承DockerFile这个还是会就会运行ONBUILD的指令,触发指令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量

实战,构建自己的centos
# 1、在home目录下新建dockerfile编写Dockerfile文件
[root@yuan dockerfile]# vim mydockerfile-centos
[root@yuan dockerfile]# cat mydockerfile-centos
FROM centos:7 #指定centos的版本为7,指定8要修改配置文件
MAINTAINER yuan<2121007706@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
#第一次要安装这两个,可能会报错
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel
RUN yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel
#安装vim
RUN yum -y install vim
#安装net-tools
RUN yun -y install net-tools
EXPOSE 80
CMD echo $MYPATH
CMD echo "----end----"
CMD /bin/bash
构建centos
2、通过这个文件构建镜像
# 命令 docker build -f dockerfile文件路径 -t 镜像名:[tag]Successfully built dc4556607d09Successfully tagged mycentos:0.1#
[root@yuan dockerfile]# docker build -f mydockerfile-centos -t mycentos:1.0 .
3、测试运行
对比:之前原生的centos

我们增加之后的镜像

我们可以列出本地镜像的变更历史:docker history 镜像id

CMD和ENTRYPOINT的区别
CMD #指定这个容器启动的时候要运行的命令,只有最后一个会生效,可背代替
ENTRYPOINT #指定这个容器启动的时候要运行的命令,可以追加命令
测试CMD
#编辑vim编辑器的内容
[root@yuan dockerfile]# vim dockerfile-cmd-test
FROM centos
#启动时执行
CMD ["ls","-a"]
#构建镜像
[root@yuan dockerfile]# docker build -f dockerfile-cmd-test -t cmdtest .
#启动镜像ls -a生效
[root@yuan dockerfile]# docker run cd92755616fe
.
..
.dockerenv
bin
dev
etc
home
#想追加-l失败报错
[root@yuan dockerfile]# docker run cd92755616fe -l
docker: Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "-l": executable file not found in $PATH: unknown.
ERRO[0000] error waiting for container: context canceled
cmd的清理下-1替换了CMD ["ls ", "-a"]命令,-1 不是命令所以报错!
测试ENTRYPOINT
#编辑vim编辑器的内容
[root@yuan dockerfile]# vim dockerfile-cmd-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
#构建镜像
[root@yuan dockerfile]# docker build -f dockerfile-cmd-entrypoint -t entrypoint-test .
#启动镜像
[root@yuan dockerfile]# docker run 180ecef10db7
.
..
.dockerenv
bin
dev
etc
home
lib
#发现追加命令成功
[root@yuan dockerfile]# docker run 180ecef10db7 -l
total 56
drwxr-xr-x 1 root root 4096 Mar 1 14:53 .
drwxr-xr-x 1 root root 4096 Mar 1 14:53 ..
-rwxr-xr-x 1 root root 0 Mar 1 14:53 .dockerenv
lrwxrwxrwx 1 root root 7 Nov 3 2020 bin -> usr/bin
drwxr-xr-x 5 root root 340 Mar 1 14:53 dev
drwxr-xr-x 1 root root 4096 Mar 1 14:53 etc
drwxr-xr-x 2 root root 4096 Nov 3 2020 home
lrwxrwxrwx 1 root root 7 Nov 3 2020 lib -> usr/lib
lrwxrwxrwx 1 root root 9 Nov 3 2020 lib64 -> usr/lib64
drwx------ 2 root root 4096 Sep 15 14:17 lost+found
drwxr-xr-x 2 root root 4096 Nov 3 2020 media
drwxr-xr-x 2 root root 4096 Nov 3 2020 mnt
drwxr-xr-x 2 root root 4096 Nov 3 2020 opt
dr-xr-xr-x 153 root root 0 Mar 1 14:53 proc
dr-xr-x--- 2 root root 4096 Sep 15 14:17 root
drwxr-xr-x 11 root root 4096 Sep 15 14:17 run
lrwxrwxrwx 1 root root 8 Nov 3 2020 sbin -> usr/sbin
drwxr-xr-x 2 root root 4096 Nov 3 2020 srv
dr-xr-xr-x 13 root root 0 Jan 31 07:54 sys
drwxrwxrwt 7 root root 4096 Sep 15 14:17 tmp
drwxr-xr-x 12 root root 4096 Sep 15 14:17 usr
drwxr-xr-x 20 root root 4096 Sep 15 14:17 var
DockerFile制作Tomcat镜像
1,环境准备:在home下新建yuan目录并拷贝文件


2、编写dockerfile文件,文件命名为Dockerfile,就不需要-f去指定了,build会自动寻找这个文件
FROM centos:7 #指定centos的版本为7
MAINTAINER yuan<2121007706@qq.com> #作者
COPY readme.txt /usr/local/readme.txt #将该目录下的文件拷贝到指定centos/usr/local目录下
ADD jdk-8u11-linux-x64.tar.gz /usr/local/ #将准备的jdk环境添加
ADD apache-tomcat-9.0.27.tar.gz /usr/local/ #添加tomcat环境
RUN yum -y install vim #安装vim
ENV MYPATH /usr/local #构建的时候设置环境变量为/usr/local
WORKDIR $MYPATH 镜像的工作目录为/usr/local
#配置jdk的环境变量
ENV JAVA_HOME /usr/local/jdk1.8.0_11
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
#配置tomcat的环境变量
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.27
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$CATALINA_HOME/bin
#指定端口
EXPOSE 8080
指定容器运行时的shell命令:镜像安装的路径/usr/local/apache-tomcat-9.0.27/bin/startup.sh启动tomcat和日志
CMD /usr/local/apache-tomcat-9.0.27/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.27/bin/logs/catalina.out
3、构建镜像
[root@yuan yuan]# docker build -t ytomcat .
4、启动镜像
[root@yuan yuan]# docker run -d -p 9090:8080 --name yuantomcat
-v /home/yuan/build/tomcat/test:/usr/local/apache-tomcat-9.0.27/webapps/test
-v /home/yuan/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.27/logs ytomcat
# 解释,第一个挂载是将webapps下的test映射到本地tomcat下的test
-v /home/eric/build/tomcat/test:/usr/local/apache-tomcat-9.0.27/webapps/test
# 解释,第二个挂载是将apache-tomcat-9.0.27下的日志映射到本地tomcat下的tomcatlogs
-v /home/eric/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.27/logs

浏览器访问:http://服务器ip地址:9090:远程服务开启端口号9090

6、发布项目(由于做了卷挂载,我们直接在本地编写项目就可以发布了)
在本地tomcat/test文件夹下创建WEB-INF文件夹,在WEB-INF下编写web.xml文件,
在/test 下编写index.jsp文件,再访问http://ip地址:9090/test/

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
</web-app>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.io.*,java.util.*, javax.servlet.*" %>
<html>
<head>
<title>hello,eric</title>
</head>
<body>
<h1>Hello Word</h1>
</body>
</html>

发布自己的镜像
2、注册账号,确定这个账号可以登录
3、登录服务器
登录命令
[root@yuan /]# docker login --help
Usage: docker login [OPTIONS] [SERVER]
Log in to a Docker registry.
If no server is specified, the default is defined by the daemon.
Options:
-p, --password string Password
--password-stdin Take the password from stdin
-u, --username string Username
测试登录
[root@yuan /]# docker login -u yuanyicheng
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
提交自己的镜像
#push的镜像有问题
[root@yuan /]# docker push yuanyicheng/ytomcat:1.0
The push refers to repository [docker.io/yuanyicheng/ytomcat]
An image does not exist locally with the tag: yuanyicheng/ytomcat
#解决增加一个tag yuanyicheng用户名作者tomcat:1.0指定版本号
[root@yuan /]# docker tag d89900068c83 yuanyicheng/tomcat:1.0
# docker psuh上去即可!自己发布的镜像尽量带上版本号
[root@yuan /]# docker push yuanyicheng/tomcat:1.0

都是由层级的关系push上去的
Docker网络
Docker网络
docker网络所有命令有误
理解网络

docker是如何处理容器网络访问的?
#清除所有的安装的容器docker rmi -f $(docker images -q)
[root@yuan ~]# docker run -d -P --name tomcat01 tomcat
# 查看容器的内部网络地址 ip addr,发现容器启动的是否会得到一个eth0@if85 ip地址,docker分配
[root@yuan ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
84: eth0@if85: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 思考Linux能不能ping通容器内部
[root@yuan ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.395 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.149 ms
# Linux可以ping通docker容器内部
原理
我们每启动一个docker容器,docker就会给docker容器分配一个ip,我们只要安装了docker,就会有一个网卡docker0桥接模式,使用的技术是evth-pair技术
再次测试ip addr,多了一对网卡

# 我们发现这些网卡都是一对对的
# veth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一段连着协议,一段彼此相连
# 正因为有这个特性veth-pair充当一个桥梁,连接各种虚拟网络设备
# OpenStack,Docker容器之间的连接,OVS的连接,都是使用veth-pair技术

结论:tomcat01和tomcat02是共用的一个路由器,docker0
所有的容器在不指定网络的情况下,都是由docker0路由的,docker会给我们的容器分配一个默认的可用ip
Docker使用的是Linux桥接,宿主机中是一个Docker容器的网桥 docker0

Docker中所有的网络接口都是虚拟的,虚拟的转发效率比较高(内网传递文件)
只要容器删除,对应的网桥就没了
容器互联--Link
#无法直接ping通
[root@yuan ~]# docker exec -it tomcat01 ping tomcat02
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "ping": executable file not found in $PATH: unknown
#通过link解决无法ping通的问题
[root@yuan ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
f5a0ca81fbe09fbfe68a774439a7060c7defd9052d0607fb6edd9fe52d02289b
[root@yuan ~]#docker exec -it tomcat03 ping tomcat02
[root@yuan ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
16a982e24a11 bridge bridge local
8136fc0f97dd host host local
21c46ca55896 none null local
[root@yuan ~]# docker inspect 16a982e24a11

探究原理
[root@yuan ~]# docker exec -it tomcat03 cat /etc/hosts
127. 0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172. 17.0.3 tomcat02 798f4caab6e3
172. 17.0.4 0050dfc49003
--link就是我们在hosts配置中增加了一个172.18.0.3 tomcat02 798f4caab6e3
其实这个tomcat03就是本地配置了tomcat02的配置
本质探究:–link就是我们在hosts配置中增加了一个172.17.0.3 tomcat02 9f6a048802b9
我们现在 玩Docker已经不建议使用–link了!
自定义网络!不适用于docker0!
自定义网络
查看所有的docker网络
docker network ls

网络模式
bridge:桥接 docker(默认,自己创建的也是使用bridge模式)
none:不配置网络
host:和宿主机共享网络
container:容器内网络连通!(用的少!局限很大)
测试
清除所有安装的容器:docker rmi -f $(docker images -q)
# 我们直接启动的命令 --net bridge 而这个就是我们的docker0
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat01 --net bridge tomcat
# docker0特点:默认,域名不能访问,--link可以打通连接
# 我么可以自定义一个网络
# 我么可以自定义一个网络
# --driver bridge
# --subnet 192.168.0.0/16 192.168.0.2 192.168.255.255
# --gateway 192.168.0.1
[root@yuan ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
02de698446c3bdb338b6333f19faca6bde36dc53718cd7fe981c70cfe125af74
[root@yuan ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
16a982e24a11 bridge bridge local
8136fc0f97dd host host local
02de698446c3 mynet bridge local
自定义的网络

[root@yuan ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
98527f2ee2cdf277eb0be601744290390663cb93b2ff7b0340b2a74c90e913c9
[root@yuan ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
e7e50b5b666d9d641a5c7ac78b034334483eaea54b6e57fc953f7cb014ce4e14

# 现在不需要使用--link也可以ping名字了!
[root@yuan ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.087 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.164 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.116 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=4 ttl=64 time=0.103 ms
**小结:**我们自定义的网络docker都已经帮我们维护好了对应的关系,推荐使用这个网络
好处:
redis - 不同集群使用不同的网络,保证集群是健康和安全的
mysql - 不同集群使用不同的网络,保证集群是健康和安全的
网络联通
测试
[root@yuan ~]# docker run -d -P --name tomcat01 tomcat
7ec75032e914fc8bc13b91ab60d2dd15f8644b1e240233a3b07b79f690206477
[root@yuan ~]# docker run -d -P --name tomcat02 tomcat
98321d687578d7bb64fe23933c9a7a6beecd9f14c405439b131615be654130a7


# 测试打通 tomcat01 - mynet
[root@yuan ~]# docker network connect mynet tomcat01
# 连通之后将tomcat01放到了mynet网络下
# 一个容器两个ip地址 阿里云服务:公网ip 私网ip

# tomcat01 和tomcat-net-01是打通的
[root@yuan ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.099 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.139 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=3 ttl=64 time=0.165 ms
# tomcat02 和tomcat-net-01是没打通的
[root@yuan ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
**结论:**如果需要跨网络操作别人,就需要使用docker network connect进行连通
Dockcer基本实战
实战:部署Redis集群

shell脚本
# 创建网卡
docker network create redis --subnet 172.38.0.0/16
# 通过脚本创建六个redis配置
for port in $(seq 1 6); \
do \
mkdir -p /mydata/redis/node-${port}/conf
touch /mydata/redis/node-${port}/conf/redis.conf
cat << EOF >/mydata/redis/node-${port}/conf/redis.conf
port 6379
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.38.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
appendonly yes
EOF
done
# 运行6个节点
docker run -p 6371:6379 -p 16371:16379 --name redis-1 \
-v /mydata/redis/node-1/data:/data \
-v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6372:6379 -p 16372:16379 --name redis-2 \
-v /mydata/redis/node-2/data:/data \
-v /mydata/redis/node-2/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.12 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6373:6379 -p 16373:16379 --name redis-3 \
-v /mydata/redis/node-3/data:/data \
-v /mydata/redis/node-3/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.13 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6374:6379 -p 16374:16379 --name redis-4 \
-v /mydata/redis/node-4/data:/data \
-v /mydata/redis/node-4/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.14 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6375:6379 -p 16375:16379 --name redis-5 \
-v /mydata/redis/node-5/data:/data \
-v /mydata/redis/node-5/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.15 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
docker run -p 6376:6379 -p 16376:16379 --name redis-6 \
-v /mydata/redis/node-6/data:/data \
-v /mydata/redis/node-6/conf/redis.conf:/etc/redis/redis.conf \
-d --net redis --ip 172.38.0.16 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
#随便进入一个redis集群
[root@yuan ~]# docker exec -it redis-1 /bin/sh
/data # ls -a
. .. appendonly.aof nodes.conf
/data #
# 创建集群通过命令:redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172
.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
/data # redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172
.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.38.0.15:6379 to 172.38.0.11:6379
Adding replica 172.38.0.16:6379 to 172.38.0.12:6379
Adding replica 172.38.0.14:6379 to 172.38.0.13:6379
M: f7c9f52f910260af33ef0e22bf2ca0063ee256ae 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
M: dae282420522b0f12f915b00e09b18fd28cf0852 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
M: 9db2e07c5d705ecb0e6564357dc019ad8ddc55c2 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
S: 1588fff8f94bf8594bc576faeceefbba8b186199 172.38.0.14:6379
replicates 9db2e07c5d705ecb0e6564357dc019ad8ddc55c2
S: 94e57f9556c1b9d58f09e37f9c31e82485b58b1c 172.38.0.15:6379
replicates f7c9f52f910260af33ef0e22bf2ca0063ee256ae
S: 5cea9d648c616337279b237f238843bde55c569b 172.38.0.16:6379
replicates dae282420522b0f12f915b00e09b18fd28cf0852
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 172.38.0.11:6379)
M: f7c9f52f910260af33ef0e22bf2ca0063ee256ae 172.38.0.11:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: dae282420522b0f12f915b00e09b18fd28cf0852 172.38.0.12:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 9db2e07c5d705ecb0e6564357dc019ad8ddc55c2 172.38.0.13:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 1588fff8f94bf8594bc576faeceefbba8b186199 172.38.0.14:6379
slots: (0 slots) slave
replicates 9db2e07c5d705ecb0e6564357dc019ad8ddc55c2
S: 5cea9d648c616337279b237f238843bde55c569b 172.38.0.16:6379
slots: (0 slots) slave
replicates dae282420522b0f12f915b00e09b18fd28cf0852
S: 94e57f9556c1b9d58f09e37f9c31e82485b58b1c 172.38.0.15:6379
slots: (0 slots) slave
replicates f7c9f52f910260af33ef0e22bf2ca0063ee256ae
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
docker搭建redis集群完成
测试
#登录reids集群
/data # redis-cli -c
#查看集群信息
127. 0.0.1:6379> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:645
cluster_stats_messages_pong_sent:657
cluster_stats_messages_sent:1302
cluster_stats_messages_ping_received:652
cluster_stats_messages_pong_received:645
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:1302

SpringBoot微服务打包Docker镜像
1、架构springboot项目
2、打包应用

3、编写Dockerfile(idea中安装docker插件比较方便)

4、将jar包和Dockerfile文件传输到Linux服务器上

5、构建镜像yuan

6、发布运行

7、测试,输出hello Docker

Docker Compose
Docker-compose简介
官网:https://docs.docker.com/compose/
Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。 Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡。 Docker-Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。 使用一个Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。 Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。 Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
Compose 是 docker 提供的一个命令行工具,用来定义和运行由多个容器组成的应用。 使用 compose,我们可以通过 YAML 文件声明式的定义应用程序的各个服务,并由单个命令完成应用的创建和启动。
Compose 的使用方式非常简单,基本上就是下面的三板斧:
- 定义 Dockerfile
- 定义 docker-compose.yml
- 运行 docker-compose up
其实 compose 提供的命令可以管理应用的整个生命周期:
- Start, stop, rebuild services
- 查看运行中 service 的状态
- 输出运行中 service 的日志
- 在 service 中执行一次性的命令
Compose是Docker官方的开源项目,需要安装
Dockerfile让程序在任何地方运行,web服务,redis、mysql、nginx…多个容器
Compose
version: "3.9" # optional since v1.27.0
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
compose安装
- 下载
#国外
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# 国内,建议使用
curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

2,授权
[root@yuan bin]# chmod +x /usr/local/bin/docker-compose

compose初体验
常用命令
在使用docker-compose命令时,默认会在当前目录下查找docker-compose.yml文件
#基于docker-compose.yml启动管理的容器
docker-compose up -d
#关闭并删除容器
docker-compose down
#开启、关闭、重启已经存在的有docker-compose管理的容器
docker-compose start|stop|restart
#查看由docker-compose管理的容器
docker-compose ps
#查看日志
docker-compose logs -f
地址:https://docs.docker.com/compose/gettingstarted/
cd /home新建一个文件
[root@yuan home]# mkdir composetest
#进入新建的目录
[root@yuan home]# cd composetest
#编辑app.py
[root@yuan composetest]# vim app.py
#查看app.py的内容
[root@yuan composetest]# cat app.py
import time
import redis
from flask import Flask
app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)
def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)
@app.route('/')
def hello():
count = get_hit_count()
return 'Hello World! I have been seen {} times.\n'.format(count)
#创建requirements.txt文件
[root@yuan composetest]# vim requirements.txt
[root@yuan composetest]# cat requirements.txt
flask
redis
#Dockerfile应用打包为镜像
#创建Dockerfile文件
[root@yuan composetest]# vim Dockerfile
[root@yuan composetest]# cat Dockerfile
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
#docker-compose.yml文件(定义整个服务于,需要的环境,web、redis)
[root@yuan composetest]# vim docker-compose.yml
[root@yuan composetest]# cat docker-compose.yml
version: "3.9"
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
#运行测试
[root@yuan composetest]# docker-compose up
docker-compose up的执行流程
1、创建网络
2、执行Docker-compose yaml
3、启动服务
Creating composetest_web_1 … done
Creating composetest_redis_1 … done




docker-compose会自动把需要的依赖下载下来

自动的默认规则
1、文件名 composetest
2、服务
默认的服务名 文件名_num
多个服务器,集群 A B_num 副本数量
服务redis服务=>4个副本
集群状态,服务都不可能只有一个运行实例。弹性、10 HA 高并发
网络规则

通过 docker network inspect composetest_default 查看compose的网络信息,在同一个网络下,通过域名访问

如果在同一个网络下,我们可以通过域名进行访问
停止
docker-compose down
或者:Ctrl+C

编写compose.yml规则
网址:https://docs.docker.com/compose/compose-file/#compose-file-structure-and-examples
# 3层
version: '' # 版本
services: # 服务
服务1: web
# 服务配置
images
build
network
......
服务2: redis
.....
服务3: mysql
.....
# 其他配置 网络/卷 全局规则
volumes:
networks:
configs

使用Compose一键部署WP博客
阿里云和宝塔要开启端口
网站地址:https://docs.docker.com/samples/wordpress/
[root@yuan home]# mkdir my_wordpress
[root@yuan home]# cd my_wordpress
[root@yuan my_wordpress]# vim docker-compose.yml
[root@yuan my_wordpress]# cat docker-compose.yml
version: "3.9"
services:
db:
image: mysql:5.7
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- wordpress_data:/var/www/html
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
wordpress_data: {}
#前台运行
[root@yuan my_wordpress]# docker-compose up
#后台运行
[root@yuan my_wordpress]# docker-compose up -d
浏览器访问:http://ip地址:8000/即可
实战编写自己的微服务上线
-
导入redis和web的依赖
-
编写文件
package com.springbootcompose.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Autowired
StringRedisTemplate redisTemplate;
@GetMapping("/hello")
public String hello(){
Long views = redisTemplate.opsForValue().increment("views");
return "hello yuan:"+views;
}
}
application.properties
server.port=9000
spring.redis.host=redis
docker-compose.yml
version: "3.8"
services:
yuanapp:
build: .
image: yuanapp
depends_on:
- redis
ports:
- "9000:9000"
redis:
image: "redis:alpine"
Dockerfile
FROM java:8
COPY *.jar /app.jar
CMD ["--server.port=9000"]
EXPOSE 9000
ENTRYPOINT ["java","-jar","/app.jar"]
- 打包镜像打服务器上

- 运行即可
docker-compose up --build
- 浏览器测试访问成功

实战编写自己的微服务上线2
准备一个jar包和一个Dockerfile文件在同级目录下

Dockerfile文件
#java环境
FROM java:1.8
#创建目录
RUN mkdir -p /news/certification
#设置工作目录
WORKDIR /news/certification
#设置时区
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
#复制jar到容器
ADD yuan-biz-0.0.1-SNAPSHOT.jar /news/certification
#启动的时候运行jave -jar包
CMD java -jar yuan-biz-0.0.1-SNAPSHOT.jar
在同级目录下输入
#-f 指定Dockerfile文件 -t去名称为new-biz
docker build -f ./Dockerfile -t new-biz .
这里进行了数据库连接需要和Mysql进行容器互联,所以还要启动mysql
docker run -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v, /root/mysql5.7/conf:/etc/mysql/conf.d \
-v /root/mysql5.7/logs:/var/log/mysql \
-v /root/mysql5.7/data:/var/lib/mysql \
--name c1_mysql mysql:5.7
最后将启动自己发布的镜像和mysql进行以Ping通,通过--link
#将news容器和c1_mysql PING通
docker run -d -p 8082:8082 --name news --link c1_mysql new-biz
最后通过浏览器访问服务器或者虚拟机

实战使用docker-compose部署

Dockerfile文件
#java环境
FROM java:1.8
#创建目录
RUN mkdir -p /news/certification
#设置工作目录
WORKDIR /news/certification
#设置时区
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
#复制jar到容器
ADD yuan-biz-0.0.1-SNAPSHOT.jar /news/certification
#启动的时候运行jave -jar包
CMD java -jar yuan-biz-0.0.1-SNAPSHOT.jar
docker-compose.yml
version: '3.1'
services:
mysql:
restart: always #只要docker启动,这个容器就会启动
image: mysql:5.7 #指定本地下载的mysql版本
container_name: c_mysql #指定mysql的名称
ports:
- 3310:3306 #对外暴露的端口3301
environment:
MYSQL_ROOT_PASSWORD: root #设置数据库密码
TZ: Asia/Shanghai #设置时区
volumes: #设置容器数据卷
- /root/mysql5.7/conf:/etc/mysql/conf.d
- /root/mysql5.7/logs:/var/log/mysql
- /root/mysql5.7/data:/var/lib/mysql
news-biz: #自己自定义Java代码的模块,名称答意即可 ,可以有多个模块
restart: always #只要docker启动,这个容器就会启动
build:
#相对于docker-comppose的路径
context: ./
#指定Dockerfile的名称
dockerfile: Dockerfile
#通过Docker构建出来的镜像名称
image: news-bizs
ports:
- 8082:8082 #暴露8082端口
#和mysql PING 通
links:
- mysql
浏览器访问

实战使用docker-compose多模块部署

docker-compose.yml
version: '3.1'
services:
mysql:
restart: always #只要docker启动,这个容器就会启动
image: mysql:5.7 #指定本地下载的mysql版本
container_name: c_mysql #指定mysql的名称
ports:
- 3310:3306 #对外暴露的端口3301
environment:
MYSQL_ROOT_PASSWORD: root #设置数据库密码
TZ: Asia/Shanghai #设置时区
volumes: #设置容器数据卷
- /root/mysql5.7/conf:/etc/mysql/conf.d
- /root/mysql5.7/logs:/var/log/mysql
- /root/mysql5.7/data:/var/lib/mysql
#这里有多少个模块就加多少个自定义模块,这里是登录模块和业务模块
news-biz: #字段自定义Java代码的模块,名称答意即可
restart: always #只要docker启动,这个容器就会启动
build:
#相对于docker-comppose的路径
context: ./news-biz
#指定Dockerfile的名称
dockerfile: Dockerfile
#通过Docker构建出来的镜像名称
image: news-biz
ports:
- 8082:8082 #暴露8082端口
#和mysql PING 通
links:
- mysql
news-login: #字段自定义Java代码的模块,名称答意即可
restart: always #只要docker启动,这个容器就会启动
build:
#相对于docker-comppose的路径
context: ./news-login
#指定Dockerfile的名称
dockerfile: Dockerfile
#通过Docker构建出来的镜像名称
image: news-login
ports:
- 8081:8081 #暴露8081端口
#和mysql PING 通
links:
- mysql
...
Docker基本软件的安装
拉取镜像报错问题
Error response from daemon: Get “https://registry-1.docker.io/v2/”: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
如果出现以上问题则需要配置文件
更换国内镜像
vim /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io/",
"https://huecker.io/",
"https://dockerhub.timeweb.cloud",
"https://noohub.ru/",
"https://dockerproxy.com",
"https://docker.mirrors.ustc.edu.cn",
"https://docker.nju.edu.cn",
"https://xx4bwyg2.mirror.aliyuncs.com",
"http://f1361db2.m.daocloud.io",
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com"
]
}
重启Docker即可
1.部署mysql
docker pull mysql:5.7
docker run -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /root/mysql5.7/conf:/etc/mysql/conf.d \
-v /root/mysql5.7/logs:/var/log/mysql \
-v /root/mysql5.7/data:/var/lib/mysql \
--name c1_mysql mysql:5.7
2.部署tomcat
docker pull tomcat:8.5
docker run -d -p 8081:8080 \
-v /root/tomcat/webapps:/usr/local/tomcat/webapps \
-v /root/tomcat/logs:/usr/local/tomcat/logs \
--name c_tomcat tomcat:8.5
try try:
/root/tomcat/webapps下创建test目录,并创建页面index.html
然后重启容器docker restart c_tomcat
浏览器输入地址访问index.html
3.部署nginx
docker pull nginx:1.21
宿主机创建vim /root/nginx/conf/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
宿主机创建vim /root/nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location ~ /*/api/ {
proxy_pass http://localhost:8690;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
运行容器
docker run -d -p 80:80 \
--privileged=true \
-v /root/nginx/log:/var/log/nginx \
-v /root/nginx/conf.d:/etc/nginx/conf.d \
-v /root/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /root/nginx/html:/usr/share/nginx/html \
--name c12_ngsssinsx nginx:1.21
4.部署nginx方法2
http://www.manongjc.com/detail/23-zukexcuusiczewg.html
上述可能会引发问题
1.首先下载nginx镜像
docker pull nginx
2.创建挂载的目录,我是放在/data/nginx里面,可自行更改
mkdir -p /data/nginx/conf #存放配置文件
mkdir -p /data/nginx/logs #存放日志相关
mkdir -p /data/nginx/html #存放html文件
mkdir -p /data/nginx/conf.d #配置nginx访问
3.因为不能挂载文件,只能挂载一个文件夹,所以我们要先创建一个测试test容器的nginx,然后复制配置文件到挂载的目录上
##启动测试容器
docker run --name test -d nginx
##复制配置文件
# test:/etc/nginx/nginx.conf /data/nginx/conf/
# 启动的容器名 nginx的文件位置 linux 自定义目录的位置
docker cp test:/etc/nginx/nginx.conf /data/nginx/conf/
docker cp test:/etc/nginx/conf.d/default.conf /data/nginx/conf.d
##如果不知道配置文件在docker里面的目录位置,可以进去看一下
docker exec -it test /bin/bash
4.然后运行你自己的nginx
docker run --name nginx01 --privileged -it -p 80:80 -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro -v /data/nginx/conf.d:/etc/nginx/conf.d:ro -v /data/nginx/html:/usr/share/nginx/html:rw -v/data/nginx/logs:/var/log/nginx -d nginx
5.最后把我们的放到html文件夹解压,重启nginx即可
##在html文件夹解压我们上传的dist文件
unzip dist.zip
##重启Jenkins
docker restart b0ba
6.最后就去访问我们的ip和端口,试试看,也可以在本机测试是否成功
curl ip:port
4.部署redis
docker run -d -p 6379:6379 --name c_redis redis:6
5.部署ElasticSearch
- 先创建/root/elasticsearch/config/elasticsearch.yml
# ======================== Elasticsearch Configuration =========================
#
# NOTE: Elasticsearch comes with reasonable defaults for most settings.
# Before you set out to tweak and tune the configuration, make sure you
# understand what are you trying to accomplish and the consequences.
#
# The primary way of configuring a node is via this file. This template lists
# the most important settings you may want to configure for a production cluster.
#
# Please consult the documentation for further information on configuration options:
# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
#
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
#cluster.name: my-application
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
#node.name: node-1
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
#path.data: /path/to/data
#
# Path to log files:
#
#path.logs: /path/to/logs
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 0.0.0.0
#
# Set a custom port for HTTP:
#
#http.port: 9200
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
#discovery.seed_hosts: ["host1", "host2"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
#cluster.initial_master_nodes: ["node-1", "node-2"]
#
# For more information, consult the discovery and cluster formation module documentation.
#
# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#
#gateway.recover_after_nodes: 3
#
# For more information, consult the gateway module documentation.
#
# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#
#action.destructive_requires_name: true
http.cors.enabled: true
http.cors.allow-origin: "*"
- 运行容器
docker run -d \
-v /root/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /root/elasticsearch/data:/usr/share/elasticsearch/data \
-v /root/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-e ES_JAVA_OPTS="-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-p 9200:9200 \
-p 9300:9300 \
--net=host \
--name c_elasticsearch elasticsearch:7.3.1
java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/nodes"
宿主机上的/root/elasticsearch/config目录权限不足导致的
chmod 777 /root/elasticsearch/data
问题描述:
宿主机不能访问容器中es
原因分析:
因为docker的虚拟ip网段是172.17.*,与局域网的ip网段不同,无法进行通信,即访问不到资源
在docker 创建和启动容器时加上 --net=host 指令,表示容器与宿主机共享同一个网卡,可以解决网段不一致的问题。
配置文件 elasticsearch.yml
network.host: 0.0.0.0
- 安装ik分词器,只要将解压后的ik分词器复制到/root/elasticsearch/plugins 目录下,重启docker容器
6.部署rabbitmq
拉取镜像
docker pull rabbitmq:3.7.14
安装运行容器
docker run -d -p 5672:5672 -p 15672:15672 \
-v /root/rabbitmq/data:/var/lib/rabbitmq \
--name c_rabbitmq rabbitmq:3.7.14
启动rabbitmq_management
docker exec -it c_rabbitmq rabbitmq-plugins enable rabbitmq_management
7.部署nocas
#拉取
docker pull nacos/nacos-server:2.0.3
#创建目录
mkdir -p /root/nacos/init.d /root/nacos/logs
#在init.d下新建文件 custom.properties
#management.endpoints.web.exposure.include=*
docker run -d -p 8848:8848 -p 9848:9848 -p 9849:9849 \
-e JVM_XMS=256m -e JVM_XMX=256m --env MODE=standalone \
-v /root/nacos/init.d/custom.properties:/home/nacos/init.d/custom.properties \
-v /root/nacos/logs:/home/nacos/logs \
--name c_nacos nacos/nacos-server:2.0.3
docker run -e JVM_XMS=256m -e JVM_XMX=256m --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server
需要打开三个端口8848 、9848 、 9849
win11安装 Docker Desktop
启用WSL
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
安装命令
**在当前目录打开cmd **
Desktop4.24.1.0.exe 下载的Desktop4.24.1.0.exe软件
D:\Program Files\Docker 安装的指定的目录
"Desktop4.24.1.0.exe" install --backend=wsl-2 --installation-dir=D:\ruanjian\docker --wsl-default-data-root=D:\Program Files\Docker\wsl --accept-license
安装成功后配置文件
{
"registry-mirrors": [
"https://82m9ar63.mirror.aliyuncs.com",
"https://mirror.ccs.tencentyun.com"
]
}
cmd输入:docker info

docker启动mysql:用户名是root