博客链接:https://www.blog.23day.site/articles/60
一款产品: 开发–上线中要有两套环境。会存在应用环境,应用配置等问题
由于版本更新等问题,导致服务不可用:对于运维来说考验很大
环境配置是十分的麻烦,每一个及其都要部署环境(集群Redis、ES、Hadoop…)
对于发布的一个项目来说 我们想可不可以直接带上环境打包(jar+Redis+Mysql等
安卓流程:java — apk —发布(应用商店)一 张三使用apk一安装即可用
docker流程: java-jar(环境) — 打包项目帯上环境(镜像) — ( Docker仓库:商店)
Docker思想来自于集装箱
隔离:Docker的核心思想。打包装箱,每个箱子都是相互隔离的,通过隔离机制,可以将服务器利用到极致
2010年,几个的年轻人,就在美国成立了一家公司 dotcloud,做一些pass的云计算服务!LXC(Linux Container容器)有关的容器技术
Linux Container容器是一种内核虚拟化技术,可以提供轻量级的虚拟化,以便隔离进程和资源。
他们将自己的技术(容器化技术)命名就是 Docker。Docker刚刚延生的时候,没有引起行业的注意
2013年,Docker开源
越来越多的人发现docker的优点。火了。Docker每个月都会更新一个版本
2014年4月9日,Docker1.0发布
docker为什么这么火,十分的轻巧
在容器技术出来之前,我们都是使用虚拟机技术
虚拟机:在window中装一个VMware,通过这个软件我们可以虚拟出来一台或者多台电脑!笨重!
虚拟机也属于虚拟化技术,Docker容器技术,也是一种虚拟化技术
虚拟机 | Docker |
---|---|
linux centos原生镜像(一个电脑) | 隔离镜像(最核心的环境 +jdk +mysql等) |
需要开启多个虚拟机 | 运行镜像就可以了 |
几GB | 几MB |
优点:
与传统虚拟机对比:
容器内的应用直接运行在宿主机的内容,容器没有自己的内核,也没有虚拟我们的硬件
应用快速的交付和部署
传统:一堆帮助文档,安装程序
Docker:打包镜像发布测试,一键运行
更便捷的升级和缩扩容
使用Docker之后,部署应用就像搭积木一样,项目打包为一个镜像,扩展服务器A 服务器B
更简单的系统运维
在容器化之后,我们的开发,测试环境都是高度一致的
更高效的计算资源应用
Docker是内核级的虚拟化,可以在一个物理机上运行很多个容器,服务器的性能可以被运用到极致
官方推荐下载步骤
#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
#4.安装docker相关的 docker-ce 社区版 而ee是企业版
yum install docker-ce docker-ce-cli containerd.io # 这里我们使用社区版即可
#5.启动docker
systemctl start docker
#6. 使用docker version查看是否按照成功
docker version
#7. 测试
docker run hello-world
第四步会出现两个问题,一个是需要提前下载一个包(或者修改一下官方给出的下载顺序
yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm
另一个是docker与podman冲突,需要卸载一下
yum erase podman buildah
删除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://axvfsf7e.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
Docker是一个Client-Server结构的系统,Docker的守护进程运行在主机上,通过Socket从客户端访问,DockerServer接受到Docker-Client的指令,就会执行这个指令
Docker为什么比VM块?
所以说新建一个容器的时候,docker不需要像虚拟机一样去加载一个操作系统内核,避免引导,虚拟机是加载Guest OS,分钟级别的,而docker是利用宿主机的操作系统,省略了复杂的过程,是秒级的
docker version #显示docker的版本信息。
docker info #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help #帮助命令
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest bf756fb1ae65 4 months ago 13.3kB
mysql 5.7 b84d68d0a7db 6 days ago 448MB
# 解释
#REPOSITORY # 镜像的仓库源
#TAG # 镜像的标签(版本) ---lastest 表示最新版本
#IMAGE ID # 镜像的id
#CREATED # 镜像的创建时间
#SIZE # 镜像的大小
# 可选项
Options:
-a, --all Show all images (default hides intermediate images) #列出所有镜像
-q, --quiet Only show numeric IDs # 只显示镜像的id
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker images -a #列出所有镜像详细信息
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker images -aq #列出所有镜像的id
d5f28a0bb0d0
f19c56ce92a8
1b6b1fe7261e
1b6b1fe7261e
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker search mysql
# --filter=STARS=3000 #过滤,搜索出来的镜像收藏STARS数量大于3000的
Options:
-f, --filter filter Filter output based on conditions provided
--format string Pretty-print search using a Go template
--limit int Max number of search results (default 25)
--no-trunc Don't truncate output
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker search mysql --filter=STARS=3000
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
mysql MySQL IS ... 9520 [OK]
mariadb MariaDB IS ... 3456 [OK]
# 下载镜像 docker pull 镜像名[:tag]
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker pull tomcat:8
8: Pulling from library/tomcat #如果不写tag,默认就是latest
90fe46dd8199: Already exists #分层下载: docker image 的核心 联合文件系统
35a4f1977689: Already exists
bbc37f14aded: Already exists
74e27dc593d4: Already exists
93a01fbfad7f: Already exists
1478df405869: Pull complete
64f0dd11682b: Pull complete
68ff4e050d11: Pull complete
f576086003cf: Pull complete
3b72593ce10e: Pull complete
Digest: sha256:0c6234e7ec9d10ab32c06423ab829b32e3183ba5bf2620ee66de866df # 签名防伪
Status: Downloaded newer image for tomcat:8
docker.io/library/tomcat:8 #真实地址
#等价于
docker pull tomcat:8
docker pull docker.io/library/tomcat:8
# docker rmi -f 镜像id #删除指定id的镜像
docker rmi -f f19c56ce92a8
# docker rmi -f $(docker images -aq) #删除全部的镜像
docker stop $(docker ps -a -q)
docker run [options] 镜像名/id [command] # 建立容器并启动:
[options]:
--name=容器名 # 命名容器以区分不同容器 tomcat01 tomcat02
-d # 在后台运行容器(必须有一个前台进程,否则进程会自动关闭)
-it # 使用交互方式运行,进入容器查看内容
-p #指定容器的端口 -p 8080(宿主机):8080(容器)
-p ip:主机端口:容器端口
-p 主机端口:容器端口(常用)
-p 容器端口
-P # 暴露容器所有端口
[command]:
/bin/bash # 控制台
docker ps 命令 #列出当前正在运行的容器
-a, --all #列出当前正在运行的容器 + 带出历史运行过的容器
-n=?, --last int #列出最近创建的?个容器 ?为1则只列出最近创建的一个容器,为2则列出2个
-q, --quiet #只列出容器的编号
exit #容器直接退出
ctrl +P +Q #容器不停止退出 ---注意:这个很有用的操作
docker rm 容器id #删除指定的容器,不能删除正在运行的容器,如果要强制删除 rm -rf
docker rm -f $(docker ps -aq) #删除所有的容器
docker ps -a -q|xargs docker rm #删除所有的容器
docker start 容器id #启动容器
docker restart 容器id #重启容器
docker stop 容器id #停止当前正在运行的容器
docker kill 容器id #强制停止当前容器
总结:
docker start/restart/stop/kill 容器名/id
docker logs -tf --tail 显示的日志条数 容器名/id # 查看日志
docker top 容器名/id # 查看容器中的进程信息
docker inspect 容器名/id # 查看镜像的元数据
docker exec -it 容器名/id /bin/bash # 通常容器以后台方式运行,需要进入其中修改配置:进入容器后开启一个新终端
docker attach 容器名/id # 进入容器正在执行的终端
docker cp 容器名/id:容器内路径 主机文件路径 # 从容器内拷贝文件到主机上
# 命令 docker run -d 镜像名
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d centos
a8f922c255859622ac45ce3a535b7a0e8253329be4756ed6e32265d2dd2fac6c
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# 问题docker ps. 发现centos 停止了
# 常见的坑,docker容器使用后台运行,就必须要有要一个前台进程,docker发现没有应用,就会自动停止
# nginx,容器启动后,发现自己没有提供服务,就会立刻停止,就是没有程序了
docker logs --help
Options:
--details Show extra details provided to logs
* -f, --follow Follow log output
--since string Show logs since timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
* --tail string Number of lines to show from the end of the logs (default "all")
* -t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
➜ ~ docker run -d centos /bin/sh -c "while true;do echo 6666;sleep 1;done" #模拟日志
#显示日志
-tf #显示日志信息(一直更新)
--tail number #需要显示日志条数
docker logs -t --tail n 容器id #查看n行日志
docker logs -ft 容器id #跟着日志
# 命令 docker top 容器id
[root@localhost ~]# docker top 4f95779df41b
UID PID PPID C STIME TTY
root 10225 10205 0 18:30 ?
root 10607 10225 0 18:34 ?
docker inspect 4f95779df41b
# 我们通常容器都是在后台运行,需要进入容器,修改一些配置
# 方式一 docker exec -it 容器id bashshell
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4f95779df41b centos "/bin/sh -c 'while t…" 10 minutes ago Up 10 minutes nostalgic_edison
[root@localhost ~]# docker exec -it 4f95779df41b /bin/bash
[root@4f95779df41b /]# ls
bin dev etc home lib lib64 lost+found media mnt opt proc root run sbin srv sys tmp usr var
# 方式二 dcoker attach 容器id
[root@localhost ~]# docker attach dce7bshk8oou7
docker exec #进入容器后开启一个新的终端
docker attach # 进入容器正在执行的终端,不会启动新的进程
docker cp 容器id:容器内路径 目的主机路径
# 查看当前主机目录下
[root@localhost home]# ls
[root@localhost home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ae552528a84 centos "/bin/bash" About a minute ago Up About a minute sleepy_kowalevski
# 进入docker容器内部
[root@localhost home]# docker exec -it 2ae552528a84 /bin/bash
[root@2ae552528a84 /]# cd /home
[root@2ae552528a84 home]# ls
# 在容器内部进行创建文件
[root@2ae552528a84 home]# touch test.java
[root@2ae552528a84 home]# exit
exit
[root@localhost home]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2ae552528a84 centos "/bin/bash" 3 minutes ago Exited (0) 6 seconds ago sleepy_kowalevski
# 见文件拷贝出来到主机上
[root@localhost home]# docker cp 2ae552528a84:/home/test.java /home
[root@localhost home]# ls
test.java
# 拷贝是一个手动过程,未来我们可以使用-v卷的技术,可以实现自动同步 /home /home
Docker的镜像实际由一层一层的文件系统组成:
对于个精简的OS,rootfs可以很小,只需要包合最基本的命令,工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的容器层。
容器在启动时会在镜像最外层上建立一层可读写的容器层(R/W),而镜像层是只读的(R/O)。
[root@localhost ~]# docker image inspect redis:latest
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:7e718b9c0c8c2e6420fe9c4d1d551088e314fe923dce4b2caf75891d82fb227d",
"sha256:89ce1a07a7e4574d724ea605b4877f8a73542cf6abd3c8cbbd2668d911fa5353",
"sha256:9eef6e3cc2937e452b2325b227ca28120a70481be25404ed9aad27fa81219fd0",
"sha256:ee748697d275b904f1d5604345d70b647a8c145b9f05aeb5ca667e1f256e43d8",
"sha256:f1f7964d40afa49c6ef63ab11af91044e518a2539f567783ce997d3cea9ce8f6",
"sha256:3d9fda8ff875e549d54e9d7504ce17d27423fe27dafbb92127c603dddad7fa13"
]
},
分层最大的好处莫过于资源共享了。比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。
所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。
举一个简单的例子,假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创健第三个镜像层该像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点.
在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而镜像包含了来自两个镜像层的6个文件。
上图中的镜像层跟之前图中的略有区別,主要目的是便于展示文件
下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版。
文种情況下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统
Linux上可用的存储引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于 Linux中对应的
件系统或者块设备技术,井且每种存储引擎都有其独有的性能特点。
Docker在 Windows上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW [1]
下图展示了与系统显示相同的三层镜像。所有镜像层堆并合井,对外提供统一的视图。
Docker镜像都是只读的,当容器启动时,一个新的可写层被加载到镜像顶部。这一层就是我们通常说的容器层,容器之下的都叫镜像层
docker commit 提交容器成为一个新的副本
# 命令和git原理类似
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[版本TAG]
为了实现数据持久化,使容器之间可以共享数据。可以将容器内的目录,挂载到宿主机上或其他容器内,实现同步和共享的操作。即使将容器删除,挂载到本地的数据卷也不会丢失。
# 匿名挂载
-v 容器内路径!
$ docker run -d -P --name nginx01 -v /etc/nginx nginx
# 查看所有的volume(卷)的情况
$ docker volume ls
DRIVER VOLUME NAME # 容器内的卷名(匿名卷挂载)
local 21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0
local b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c
# 这里发现,这种就是匿名挂载,我们在 -v只写了容器内的路径,没有写容器外的路径
# 具名挂载 -P:表示随机映射端口
$ docker run -d -P --name nginx02 -v juming-nginx:/etc/nginx nginx
9663cfcb1e5a9a1548867481bfddab9fd7824a6dc4c778bf438a040fe891f0ee
# 查看所有的volume(卷)的情况
$ docker volume ls
DRIVER VOLUME NAME
local 21159a8518abd468728cdbe8594a75b204a10c26be6c36090cde1ee88965f0d0
local b17f52d38f528893dd5720899f555caf22b31bf50b0680e7c6d5431dbda2802c
local juming-nginx #多了一个名字
# 通过 -v 卷名:查看容器内路径
# 查看一下这个卷
$ docker volume inspect juming-nginx
[
{
"CreatedAt": "2020-05-23T13:55:34+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data", #默认目录
"Name": "juming-nginx",
"Options": null,
"Scope": "local"
}
]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l12KaM1J-1644282103817)(img/Docker/image-20220207153554831.png)]
所有docker容器内的卷,在未指定主机内目录时,都在:/var/lib/docker/volumes/卷名/_data 下,可通过具名挂载可以方便的找到卷,因此广泛使用这种方式进行挂载。
# 三种挂载: 匿名挂载、具名挂载、指定路径挂载
-v 容器内路径 #匿名挂载
-v 卷名:容器内路径 #具名挂载
-v /宿主机路径:容器内路径 #指定路径挂载 docker volume ls 是查看不到的
# 通过 -v 容器内路径: ro rw 改变读写权限
ro #readonly 只读
rw #readwrite 可读可写
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:ro nginx
$ docker run -d -P --name nginx05 -v juming:/etc/nginx:rw nginx
# ro 只要看到ro就说明这个路径只能通过宿主机来操作,容器内部是无法操作!
重点:三个容器的共享卷均挂载到宿主机的某物理地址,而不是三个容器间实现的互相拷贝或者引用
# 测试 启动3个容器
# 创建docker01
$ docker run -it --name docker01 centos
# 查看容器docekr01内容
$ ls
bin home lost+found opt run sys var
dev lib media proc sbin tmp volume01
etc lib64 mnt root srv usr volume02
# 不关闭该容器退出
CTRL + Q + P
# 创建docker02: 并且让docker02 继承 docker01
$ docker run -it --name docker02 --volumes-from docker01 centos
# 查看容器docker02内容
$ ls
bin home lost+found opt run sys var
dev lib media proc sbin tmp volume01
etc lib64 mnt root srv usr volume02
# 再新建一个docker03同样继承docker01
$ docker run -it --name docker03 --volumes-from docker01 centos
$ cd volume01 #进入volume01 查看是否也同步docker01的数据
$ ls
docker01.txt
# 测试:可以删除docker01,查看一下docker02和docker03是否可以访问这个文件
# 测试发现:数据依旧保留在docker02和docker03中没有被删除
# 1、搜索镜像
[root@localhost home]# docker search nginx
# 2、拉取镜像
[root@localhost home]# docker pull nginx
# 3、查看镜像
[root@localhost home]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 62d49f9bab67 3 weeks ago 133MB
centos latest 300e315adb2f 4 months ago 209MB
# 4、启动运行
[root@localhost home]# docker run -d --name nginx01 -p 3344:80 nginx
66f84ea1a1679cc5f062e4c7aab26f051d30df710e23e7685597257933eb7d61
# 5、查看运行情况
[root@localhost home]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
66f84ea1a167 nginx "/docker-entrypoint.…" 31 seconds ago Up 29 seconds 0.0.0.0:3344->80/tcp, :::3344->80/tcp nginx01
# 6、本机自测运行情况
[root@localhost home]# curl localhost:3344
# 7、进入容器,修改配置
[root@localhost home]# docker exec -it nginx01 /bin/bash
root@66f84ea1a167:/# whereis nginx
nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx
root@66f84ea1a167:/# cd /etc/nginx
# 之前的启动都是后台,停止了容器,容器还是可以查到, docker run -it --rm 镜像名 一般是用来测试,用完就删除容器
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -it --rm tomcat:9.0
--rm Automatically remove the container when it exits 用完即删
#下载
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker pull tomcat
#查看下载的镜像
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker images
#以后台方式,暴露端口方式,启动运行
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker run -d -p 8080:8080 --name tomcat01 tomcat
#测试访问有没有问题
curl localhost:8080
#根据容器id进入tomcat容器
[root@iz2zeak7sgj6i7hrb2g862z ~]# docker exec -it 645596565d3f /bin/bash
root@645596565d3f:/usr/local/tomcat#
#查看tomcat容器内部内容:
root@645596565d3f:/usr/local/tomcat# ls -l
total 152
-rw-r--r-- 1 root root 18982 May 5 20:40 BUILDING.txt
-rw-r--r-- 1 root root 5409 May 5 20:40 CONTRIBUTING.md
-rw-r--r-- 1 root root 57092 May 5 20:40 LICENSE
-rw-r--r-- 1 root root 2333 May 5 20:40 NOTICE
-rw-r--r-- 1 root root 3255 May 5 20:40 README.md
-rw-r--r-- 1 root root 6898 May 5 20:40 RELEASE-NOTES
-rw-r--r-- 1 root root 16262 May 5 20:40 RUNNING.txt
drwxr-xr-x 2 root root 4096 May 16 12:05 bin
drwxr-xr-x 1 root root 4096 May 21 11:04 conf
drwxr-xr-x 2 root root 4096 May 16 12:05 lib
drwxrwxrwx 1 root root 4096 May 21 11:04 logs
drwxr-xr-x 2 root root 4096 May 16 12:05 native-jni-lib
drwxrwxrwx 2 root root 4096 May 16 12:05 temp
drwxr-xr-x 2 root root 4096 May 16 12:05 webapps
drwxr-xr-x 7 root root 4096 May 5 20:37 webapps.dist
drwxrwxrwx 2 root root 4096 May 5 20:36 work
root@645596565d3f:/usr/local/tomcat#
#进入webapps目录
root@645596565d3f:/usr/local/tomcat# cd webapps
root@645596565d3f:/usr/local/tomcat/webapps# ls
root@645596565d3f:/usr/local/tomcat/webapps#
# 发现问题:1、linux命令少了。 2.webapps目录为空
# 原因:阿里云镜像的原因,阿里云默认是最小的镜像,所以不必要的都剔除掉
# 保证最小可运行的环境!
# 解决方案:
# 将webapps.dist下的文件都拷贝到webapps下即可
root@645596565d3f:/usr/local/tomcat# ls
# 找到webapps.dist
BUILDING.txt LICENSE README.md RUNNING.txt conf logs temp webapps.dist
CONTRIBUTING.md NOTICE RELEASE-NOTES bin lib native-jni-lib webapps work
root@645596565d3f:/usr/local/tomcat# cd webapps.dist/
# 进入webapps.dist
root@645596565d3f:/usr/local/tomcat/webapps.dist# ls
ROOT docs examples host-manager manager
root@645596565d3f:/usr/local/tomcat/webapps.dist# cd ..
root@645596565d3f:/usr/local/tomcat# cp -r webapps.dist/* webapps
# 拷贝webapps.dist 内容给webapps
root@645596565d3f:/usr/local/tomcat# cd webapps
#进入webapps
root@645596565d3f:/usr/local/tomcat/webapps# ls
#查看拷贝结果
ROOT docs examples host-manager manager
# 获取mysql镜像
[root@iz2zeak7sgj6i7hrb2g862z home]# docker pull mysql
# 运行容器,需要做数据挂载
#安装启动mysql,需要配置密码的,这是要注意点
# 参考官网hub
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag
#启动
-d 后台运行
-p 端口映射
-v 卷挂载
-e 环境配置
-- name 容器名字
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 mysql00 mysql
# 启动成功之后,我们在本地使用workbench来测试一下
# workbench-连接到服务器的3306--和容器内的3306映射
# 在本地测试创建一个数据库,查看一下我们映射的路径是否ok!
portainer
docker run -d -p 8080:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer
dockerfile是用来构建docker镜像的文件,命令参数脚本
dockerfile是面向开发的,我们以后要发布项目,做镜像,就需要编写dockerfile文件
步骤:
编写一个dockerfile文件
docker build 构建称为一个镜像
docker run运行镜像
docker push发布镜像(DockerHub 、阿里云仓库)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4PPqwKJY-1644282103818)(img/Docker/411dbfc840cd72f6a493af6daff574d0.png)]
FROM # 基础镜像,一切从这里开始
MAINTAINER # 镜像是谁写的,姓名+邮箱
RUN # 镜像构建的时候需要运行的命令
ADD # 步骤:tomcat镜像,这个tomcat压缩包,添加内容
WORKDIR # 镜像的工作目录
VOLUME #挂载的目录
EXPOSE # 暴露端口配置
CMD # 指定容器运行时的shell命令,只有最后一个生效,可被替代
ENTRYPOINT # 指定容器运行时的shell命令,可以追加命令
ONBUILD # 当构建一个被继承DockerFile这个还是会就会运行ONBUILD的指令,触发指令
COPY # 类似ADD,将我们文件拷贝到镜像中
ENV # 构建的时候设置环境变量
# 1./home下新建dockerfile目录
$ mkdir dockerfile
# 2. dockerfile目录下新建mydockerfile文件
$ vim mydockerfile
# 3.编写Dockerfile配置文件
FROM centos # 基础镜像是官方原生的centos
MAINTAINER username<123465@qq.com> # 作者
ENV MYPATH /usr/local # 配置环境变量的目录
WORKDIR $MYPATH # 将工作目录设置为 MYPATH
RUN yum -y install vim # 给官方原生的centos 增加 vim指令
RUN yum -y install net-tools # 给官方原生的centos 增加 ifconfig命令
# 在最新的centos8中因为没有配置源 所以这个命令无法执行
EXPOSE 80 # 暴露端口号为80
CMD echo $MYPATH # 输出下 MYPATH 路径
CMD echo "-----end----"
CMD /bin/bash # 启动后进入 /bin/bash
# 4.通过这个文件构建镜像
# 命令: docker build -f 文件路径 -t 镜像名:[tag] .
$ docker build -f mydockerfile -t mycentos:0.1 .
# 5.查看镜像
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mycentos 0.1 cbf5110a646d 2 minutes ago 311MB
# 6.测试运行
$ docker run -it mycentos:0.1 # 注意带上版本号,否则每次都回去找最新版latest
$ pwd
/usr/local # 与Dockerfile文件中 WORKDIR 设置的 MYPATH 一致
$ vim # vim 指令可以使用
$ ifconfig # ifconfig 指令可以使用
# 7.docker history 镜像id 查看镜像构建历史步骤
$ docker history 镜像id
CMD:
# 编写dockerfile文件
$ vim dockerfile-test-cmd
FROM centos
CMD ["ls","-a"] # 启动后执行 ls -a 命令
# 构建镜像
$ docker build -f dockerfile-test-cmd -t cmd-test:0.1 .
# 运行镜像
$ docker run cmd-test:0.1 # 由结果可得,运行后就执行了 ls -a 命令
.
..
.dockerenv
bin
dev
etc
home
# 想追加一个命令 -l 成为ls -al:展示列表详细数据
$ docker run cmd-test:0.1 -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.
ERRO[0000] error waiting for container: context canceled
# cmd的情况下 -l 替换了CMD["ls","-l"] 而 -l 不是命令所以报错
ENTRYPOINT:
# 编写dockerfile文件
$ vim dockerfile-test-entrypoint
FROM centos
ENTRYPOINT ["ls","-a"]
# 构建镜像
$ docker build -f dockerfile-test-entrypoint -t cmd-test:0.1 .
# 运行镜像
$ docker run entrypoint-test:0.1
.
..
.dockerenv
bin
dev
etc
# 我们的命令,是直接拼接在我们得ENTRYPOINT命令后面的
$ docker run entrypoint-test:0.1 -l
total 56
drwxr-xr-x 1 root root 4096 May 16 06:32 .
drwxr-xr-x 1 root root 4096 May 16 06:32 ..
-rwxr-xr-x 1 root root 0 May 16 06:32 .dockerenv
lrwxrwxrwx 1 root root 7 May 11 2019 bin -> usr/bin
drwxr-xr-x 5 root root 340 May 16 06:32 dev
准备tomcat 和 jdk 到当前目录,编写好README
FROM centos # 基础镜像centos
MAINTAINER cao<1165680007@qq.com> # 作者
COPY README /usr/local/README # 复制README文件
ADD jdk-8u231-linux-x64.tar.gz /usr/local/ # 添加jdk,ADD 命令会自动解压
ADD apache-tomcat-9.0.35.tar.gz /usr/local/ # 添加tomcat,ADD 命令会自动解压
RUN yum -y install vim # 安装 vim 命令
ENV MYPATH /usr/local # 环境变量设置 工作目录
WORKDIR $MYPATH
ENV JAVA_HOME /usr/local/jdk1.8.0_231 # 环境变量: JAVA_HOME环境变量
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.35 # 环境变量: tomcat环境变量
ENV CATALINA_BASH /usr/local/apache-tomcat-9.0.35
# 设置环境变量 分隔符是:
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
EXPOSE 8080 # 设置暴露的端口
CMD /usr/local/apache-tomcat-9.0.35/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.35/logs/catalina.out
docker build -t mytomcat:0.1 .
# -d:后台运行 -p:暴露端口 --name:别名 -v:绑定路径
$ docker run -d -p 8080:8080 --name tomcat01
-v /home/kuangshen/build/tomcat/test:/usr/local/apache-tomcat-9.0.35/webapps/test
-v /home/kuangshen/build/tomcat/tomcatlogs/:/usr/local/apache-tomcat-9.0.35/logs mytomcat:0.1
$ docker exec -it 自定义容器的id /bin/bash
$ cul localhost:8080
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yDefQuR0-1644282103819)(img/Docker/cab627703fe9866a82d682e5951da112.png)]
[root@localhost ~]# docker run -d -P --name tomcat01 tomcat
# 查看容器的内部网络地址 ip addr,发现容器启动的是否会得到一个eth0@if85 ip地址,docker分配
[root@localhost ~]# 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@localhost ~]# 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容器内部
原理:
我们发现这些网卡都是一对对的
veth-pair 就是一对的虚拟设备接口,它们都是成对出现的,一段连着协议,一段彼此相连
我们每启动一个docker容器,docker就会给容器分配一个默认的可用ip,我们只要安装了docker,就会有一个网卡docker0(bridge)。网卡采用桥接模式,并使用veth-pair技术(veth-pair就是一堆虚拟设备接口,成对出现,一段连着协议,一段彼此相连,充当一个桥梁。)。
3、我们来测试下tomcat01和tomcat02是否可以ping通
# 获取tomcat01的ip 172.17.0.2
$ docker-tomcat docker exec -it tomcat01 ip addr
550: eth0@if551: <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
# 让tomcat02 ping tomcat01
$ docker-tomcat docker exec -it tomcat02 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.098 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.071 ms
结论:
tomcat01和tomcat02是共用的一个路由器,docker0
所有的容器在不指定网络的情况下,都是由docker0路由的,docker会给我们的容器分配一个默认的可用ip
Docker使用的是Linux的桥接,宿主机是一个Docker容器的网桥 docker0
Docker中所有网络接口都是虚拟的,虚拟的转发效率高(内网传递文件)
$ docker exec -it tomcat02 ping tomca01 # ping不通
ping: tomca01: Name or service not known
# 运行一个tomcat03 --link tomcat02
$ docker run -d -P --name tomcat03 --link tomcat02 tomcat
5f9331566980a9e92bc54681caaac14e9fc993f14ad13d98534026c08c0a9aef
# 3连接2
# 用tomcat03 ping tomcat02 可以ping通
$ docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.115 ms
64 bytes from tomcat02 (172.17.0.3): icmp_seq=2 ttl=64 time=0.080 ms
# 2连接3
# 用tomcat02 ping tomcat03 ping不通
–link 本质就是在hosts配置中添加映射
现在使用Docker已经不建议使用–link了!
docker network
connect -- Connect a container to a network
create -- Creates a new network with a name specified by the
disconnect -- Disconnects a container from a network
inspect -- Displays detailed information on a network
ls -- Lists all the networks created by the user
prune -- Remove all unused networks
rm -- Deletes one or more networks
网络模式
bridge :桥接 docker(默认,自己创建也是用bridge模式)
none :不配置网络,一般不用
host :和所主机共享网络
container :容器网络连通(用得少!局限很大)
测试
# 我们直接启动的命令 默认参数:--net bridge,而这个就是我们得docker0
# 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@localhost ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
7637416b83c39b59e8af8e5b79f95f55b2cf3700017a547c3b5f2596fa637fd2
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
e57926bed59d bridge bridge local
b97cfa843b69 host host local
7637416b83c3 mynet bridge local
12a56a664499 none null local
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QXPYXxo3-1644282103824)(img/Docker/abe7609e2eaff96767fb63e00e15ab74.png)]
[root@localhost ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
959374947ce0f666073cd160b0ed3f727c72f24f907754c62d377d66d48b885d
[root@localhost ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
7b6b415d88222daf44c8542121cd7256e398fb4dd2880c74a8d4db0077245a8b
[root@localhost ~]# docker network inspect mynet
{
"Name": "mynet",
"Id": "7637416b83c39b59e8af8e5b79f95f55b2cf3700017a547c3b5f2596fa637fd2",
"Driver": "bridge",
"IPAM": {
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
"Containers": {
"7b6b415d88222daf44c8542121cd7256e398fb4dd2880c74a8d4db0077245a8b": {
"Name": "tomcat-net-02",
"EndpointID": "9c8a2979e3c1b9914fde4502298ec3aa35bd004a178d695222629fc613f482df",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"959374947ce0f666073cd160b0ed3f727c72f24f907754c62d377d66d48b885d": {
"Name": "tomcat-net-01",
"EndpointID": "b98aee7d07ecaea623dad5318076b32dd67bbb7a4eafa35e6d1e9605ab71f661",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
# 再次测试ping连接
[root@localhost ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.177 ms
64 bytes from 192.168.0.3: icmp_seq=5 ttl=64 time=0.135 ms
# 现在不需要使用--link也可以ping名字了!
[root@localhost ~]# 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=4 ttl=64 time=0.103 ms
对于建立在不同网络下(docker0, newnet)的两个容器tomcat01和tomcat02,他们的网段不同,因此是无法彼此ping通容器内部的
这时我们需要通过docker network connect命令打通容器与网络之间的连接
# 测试打通 tomcat01 - mynet
[root@localhost ~]# docker network connect mynet tomcat01
# 连通之后将tomcat01放到了mynet网络下
# 一个容器两个ip地址 阿里云服务:公网ip 私网ip