一款产品:开发–上线,两套环境,环境配置比较麻烦,
发布项目每个机器都要部署环境(集群Redis、JDK、ES、Hadoop、Mysql等),不能跨平台。
传统:开发出jar,运维部署
现在:开发打包部署一条龙
jar – apk – 发布应用商店 --客户下载apk安装
jar(环境) – 打包项目带上环境(镜像) – Docker仓库(商店) --下载镜像 --可直接运行
版本更新导致服务不可用,
vm: linux原生镜像(几个G),隔离需要开启多个VM ,启动几分钟
docker:自带隔离,镜像(最核心的环境4M),轻巧,秒级启动
go语言开发,开源
Docker命令docker version #版本信息 docker info #系统信息,包括镜像和容器 docker --help docker xxx --help docker stats #查看资源使用情况镜像命令
docker images #本地主机上的镜像(id,name等) docker search xxx #仓库搜索镜像 类似于gitHub的搜索 docker pull #拉取镜像 docker pull mysql:5.7 docker rmi id/name #删除镜像容器命令
有了镜像才可以创建容器,类似于Class new instance
docker pull centos #下载centos镜像练习
新建容器并启动
docker run[可选参数] image #参数说明 --name="name" #容器名字 -d #后台运行 -it #交互方式运行,进入容器查看内容 -P #大写,指定容器的端口 -P 8080 -P ip:主机端口:容器端口 -P 主机端口:容器端口(常用) -P 容器端口 容器端口 -p #小写,随机指定端口 docker run -it --name mynginx -P 3344:80 nginx # 3344对外端口 映射到内部端口80
#测试:启动进入容器
docker run -it centos /bin/bash #启动并进入centos容器
ctrl+p+q #退出容器
exit #停止退出容器
docker ps[参数]
ps #查看当前运行的容器
ps -a #a=all查看正在运行+历史运行的容器
ps -a -n=1 #查看最近运行的容器
ps -aq #查看所有容器
docker rm #删除容器
docker rm id #删除指定容器 ,运行中的不能删除
docker rm -f $(docker ps -aq) #递归删除所有容器 ,运行中的强制删除
docker ps -a -q|xargs #查看所有容器通过管道删除
docker start 容器id #启动容器
docker restart 容器id #
docker stop 容器id #
docker kill 容器id #
日志
docker log -tf --tail 10 容器id # -tf显示日志 --tail显示条数进程
docker top 容器id #查看容器中的进程容器元数据
docker inspect 容器id #查看容器的元数据进入当前正在运行的容器
docker exec -it 容器id /bin/bash #进入容器 方式一 新的终端(常用) docker attach 容器id #进入容器 方式二拷贝数据 容器到主机
docker cp 容器id:path/file /path(目标路径)demo 搭建nginx
docker images #1 查看镜像 REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest feb5d9fea6a5 7 months ago 13.3kB centos latest 5d0da3dc9764 7 months ago 231MB docker search nginx NAME DESCRIPTION STARS OFFICIAL AUTOMATED nginx Official build of Nginx. 16670 [OK] bitnami/nginx Bitnami nginx Docker Image 122 [OK] docker pull nginx #2 拉取镜像 Using default tag: latest latest: Pulling from library/nginx 1fe172e4850f: Pull complete 35c195f487df: Pull complete 213b9b16f495: Pull complete a8172d9e19b9: Pull complete f5eee2cb2150: Pull complete 93e404ba8667: Pull complete Digest: sha256:859ab6768a6f26a79bc42b231664111317d095a4f04e4b6fe79ce37b3d199097 Status: Downloaded newer image for nginx:latest docker.io/library/nginx:latest docker run --name hot-nginx -d -p 8080:80 nginx #3 run运行 --name别名 -p 8080:80 宿主机端口:容器端口 8301c8a262ce7fc5e40c828e0e4378dbf1d25f453cacfc6ed39ebd6c29d0f2c7 C:UsersThinkPad>docker ps #4 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8301c8a262ce nginx "/docker-entrypoint.…" 43 seconds ago Up 41 seconds 0.0.0.0:8080->80/tcp hot-nginx 199923305a43 centos "/bin/bash" 29 minutes ago Up 29 minutes hotLinux culr localhost:8080 #5 外部模拟访问nginx搭建tomcatWelcome to nginx! Welcome to nginx!
If you see this page, the nginx web server is successfully installed and working. Further configuration is required.
For online documentation and support please refer to nginx.org.
Commercial support is available at nginx.com.Thank you for using nginx.
docker exec -it hot-nginx /bin/bash #6 进入nginx容器 root@8301c8a262ce:/# root@8301c8a262ce:/# whereis nginx #7 查找nginx文件 nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx root@8301c8a262ce:/# cd etc/nginx/ root@8301c8a262ce:/etc/nginx# ls conf.d fastcgi_params mime.types modules nginx.conf scgi_params uwsgi_params root@8301c8a262ce:/etc/nginx# whereis nginxread escape sequence #8 ctrl+p+q退出容器 C:UsersThinkPad>docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8301c8a262ce nginx "/docker-entrypoint.…" 39 minutes ago Up 39 minutes 0.0.0.0:8080->80/tcp hot-nginx 199923305a43 centos "/bin/bash" About an hour ago Up About an hour hotLinux C:UsersThinkPad>docker stop 8301c8a262ce #9关闭容器 8301c8a262ce C:UsersThinkPad> #10 修改配置文件要进入到容器内部比较麻烦,可在容器外部提供一个映射路径在外部修改 # -V数据卷
docker search tomcat docker pull tomcat docker run -d -p 8081:8080 --name hot-tomcat tomcat 访问测试 HTTP状态 404 - 未找到 docker exec -it hot-tomcat /bin/bash #进入容器查看 webapps是空的 :阉割版,只保证可运行的最小环境 root@1705c98b8384:/usr/local/tomcat# ls 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@1705c98b8384:/usr/local/tomcat# cd webapps root@1705c98b8384:/usr/local/tomcat/webapps# ls root@1705c98b8384:/usr/local/tomcat/webapps# cp -r webapps.dist/* webapps # 拷贝webapps.dist到webapps 访问成功 Apache Tomcat/10.0.20搭建ES+Kibana
#elasticsearch #暴露的端口很多 #十分耗内存 #数据一般放到安全目录,挂载 #网络配置 #创建用户定义的网络(用于连接到连接到同一网络的其他服务(例如 Kibana)): docker network create somenetwork # ① Run Elasticsearch docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:tag docker stats #查看资源使用情况 #测试访问 curl localhost:9200 # ② Run Elasticsearch 十分耗内存,可以限制内存,修改配置文件 -e环境配置修改 docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="Xms64m Xmx=512m" elasticsearch:tag docker stats #查看资源使用情况 #测试访问 curl localhost:9200可视化 portainer
Docker图形化界面管理工具
#安装 docker run --name portainer --restart always -d -p 8000:8000 -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer docker run -d -p 8000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --privileged=true portainer/portainer docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainerRancher(DI/CD用) Docker镜像加载原理 UnionFS
UnionFS(联合文件系统):是一种分层,轻量级高性能的文件系统,它支持对文件系统的修改作为一次提交来一层一层叠加,同时可以将不同目录挂载到一个虚拟文件系统下,Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作具体的应用镜像。
特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录
Docker镜像加载原理:docker的镜像实际是由一层一层的文件系统组成,这种层级的文件系统就是unionFS(联合文件系统)
bootfsboot file system
系统启动需要引导加载,主要包含bootloader和kernel,bootloader引导加载kernel(黑屏–>加载–>开机进入系统),Linux启动时候会加载bootfs文件系统,当bootfs加载完成后整个内核就在内存中,此时内存使用权由bootfs转交给内核,系统卸载bootfs。
Docker镜像的最底层也是bootfs,可以和Linux共用
rootfsroot file system
在bootfs之上,包含的就是典型的Linux文件系统,如 /dev,/proc,/bin,/etc等标准目录和文件
所以一个容器也就是一个迷你的虚拟机环境
对于一个精简版的OS,rootfs可以很小,只需要包含基本的命令,工具和程序库就可以了,因为底层可以共用主机的kernel,自己只需要提供footfs就可以了,所以容器的Linux是200多M大小,不同发行版本的Linux,bootfs基本一致,只是rootfs会由差别,所以不同的发行版本可以共用bootfs。
虚拟机启动分钟级Docker是秒级的原因就在此。
镜像分层原理docker pull redis
Using default tag: latest
latest: Pulling from library/redis
1fe172e4850f: Already exists #已经存在不需要再次下载
6fbcd347bf99: Pull complete
993114c67627: Pull complete
2a560260ca39: Pull complete
b7179886a292: Pull complete
8901ffe2be84: Pull complete
Digest: sha256:b7fd1a2c89d09a836f659d72c52d27b9f71202c97014a47639f87c992e8c0f1b
Status: Downloaded newer image for redis:latest
docker.io/library/redis:latest
docker image inspect redis:latest #查看redis镜像元数据
#分层记录 layers 6层
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:9c1b6dd6c1e6be9fdd2b1987783824670d3b0dd7ae8ad6f57dc3cea5739ac71e",
"sha256:d65e371da0453ddb98c6be22dcc90e7a6eb875e2132210657dde8322cb257dc6",
"sha256:f0228b605b4af7181c89c268d333a0d41d815fe30dda1e7f481f02dee3642d27",
"sha256:b959234ba79a363e2ebbdb652b33de94df87c24ba63d78c34b8c0823930cd94c",
"sha256:cfcecd8b0c43b02f466e77a62b0e507df795d752f32fafb37c9a88e00e9d1934",
"sha256:65d8db3af33580e3274c7dbea66651b51e2d74dce04c3a7ad8292b039275eed3"
]
},
所有的Docker镜像都起始于一个基础镜像层,当进行修改或新增内容时,就会在当前镜像层上创建新的镜像层供操作
Docker镜像都是只读的,当容器启动时一个新的可写层被加载到镜像的顶部,这个就是容器层
commit镜像demo
pull的tomcat webapps里是空的,把webapps.dist里的文件复制到webapps,相当于修改后的tomcat,提交成一个自己的镜像
docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[TAG] #TAG类似于git的版本,可以回滚容器数据卷
容器之间可以有一个数据共享的技术,Docker容器中产生的数据同步到本地持久化,这就是卷技术。目录的挂载,将容器的目录挂载到Linux上
-v #方式一:命令挂载
docker run -it -v /home/test:/home centos /bin/bash #/home/test linux目录 /home centos /bin/bash 容器目录
#退出容器
ctrl+p+q
#查看容器元数据
C:UsersThinkPad>docker inspect d6424028f50e
"Mounts": [ #挂载 -V卷
{
"Type": "bind", #绑定(双向)
"Source": "/home/test", #主机目录
"Destination": "/home", #docker容器目录
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
demo
docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag docker run -d -p 3306:3306 -v /home/mysql/conf:/ect/mysql/conf.d -v/home/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=501920431 --name hot-mysql mysql:tag -d#后台运行 -p#端口映射 -P#随机端口 -v#卷挂载 -e#环境配置 --name#容器名字具名挂载、匿名挂载
#匿名挂载 -v 容器内路径 docker run -d -P --name mynginx -v /etc/nginx nginx #查看卷数据 volume docker volume ls #具名挂载 -v 卷名:容器内路径 docker run -d -P --name mynginx -v juming-nginx: /etc/nginx nginx #查看卷数据 ,所有docker容器内的卷匿名挂载(没用指定目录)的都是在该目录下 /var/lib/docker/volume/xxx/-data docker volume inspect juming-nginx #指定路径挂载 -v /宿主机路径:容器内路径 #指定路径挂载并分配权限 ro=readonly rw=readwrite readonly容器只读,只能从宿主机来操作 docker run -d -P --name mynginx -v juming-nginx: /etc/nginx:ro nginx docker run -d -P --name mynginx -v juming-nginx: /etc/nginx:rw nginxDockerFile
手工构建容器镜像文件,类似commit一样,
1.编写dockerfile文件
2.docker build构建成镜像文件(image)
3.docker run运行镜像提供服务
4.docker push发布镜像(docker Hub,第三方镜像仓库,如阿里云镜像仓库等)
#通过脚本生成镜像 makdir docker-test-volume pwd vim dockerfile1
#镜像是分层的layer,命令也一样一层一层构建 ,命令指令都是大写 FROME centos #以centos为基础 VOLUME ["volume1","volume2"] #挂载卷,容器内目录 匿名挂载,如果没在此挂载,需要手动挂载 -v 卷名:容器内路径 CMD echo "-----end" #构建完成提示 CMD /bin/bash #构建完进入binbash目录 wq
cat dockerfile1 #查看dockerfile1脚本 #构建镜像 docker build -f /home/docker-test-volume dockerfile1 -t /hot/centos:1.0 . #查看镜像 docker images #启动容器 docker run -it 容器id /bin/bash #查看容器目录 ls -l #生成镜像时候自动挂载的目录,也就是数据卷目录,在宿主机一定存在映射目录 volume1 volume2 #查看容器元数据查看映射目录 docker inspect 容器id "Mounts": ["source":"filepath"] #测试挂载同步,进入容器创建文件 touch test.txtDockerFike指令
#都是大写 FROM #基础镜像 如:centos MAINTAINER #镜像作者,姓名+邮箱 RUN #镜像构建的时候需要运行的命令 ADD #添加的内容 如:tomcat压缩包 WORKDIR #镜像工作目录 VOLUME #设置卷,挂载主机目录 EXPOSE #暴露端口配置 CMD #指定容器启动的时候需要执行的命令 如:CMD echo输出信息 ls列出目录等, ENTRYPOINT #指定容器启动的时候需要执行的命令,这两个是有区别的 CMD会替换命令,ENTRYPOINT不会替换,追加 ONBUILD #构建一个被继承的DockerFile,这个时候就运行ONBUILD指令。触发指令 COPY #类似于ADD,将文件拷贝到镜像中 ENV #构建的时候设置环境变量
官网的镜像有构建方式,可以参考
数据卷容器容器之间的数据同步,如多个mysql同步数据
demo#启动3个镜像测试 ,据卷容器删了,挂载容器的数据不会丢失 #docker01 docker images docker run -it --name docker01 hot/centos:1.0 #看到挂载的数据卷volume1和volume2 ls-l #docker02 ctrl+p+q #退出docker01 #查看docker01是否启动 docker ps #docker02挂载docker01,docker01就叫数据卷容器 docker run -it --name docker02 --volums-from docker01 hot/centos:1.0 #进入容器1数据卷创建文件 docker attach 容器id ls-l cd volume1 touch docker01test #进入容器2数据卷查看同步文件 docker attach 容器id ls-l cd volume1 ls #docker03 ctrl+p+q #退出docker02 #查看docker02是否启动 docker ps #docker03挂载docker01,docker01就叫数据卷容器 docker run -it --name docker03 --volums-from docker01 hot/centos:1.0 #查看镜像构建历史 docker history 容器id
结论:容器之间配置信息的传递(集群),数据卷的生命周期=容器生命周期
但是一但持久化到本地了,数据是不会删的
Docker网络 Docker0 –link 自定义网络docker network ls网络模式
桥接:默认,docker搭桥,只能通过一个,自定义也是用这个
none:不配置网络
host:和宿主机共享网络
container:容器内网络连同(不建议使用)
自定义网络(桥接模式)
docker run -d -p --name tomcat01 tomcat docker run -d -p --name tomcat01 --net bridge tomcat docker network --help docker network create --help #自定义网络 #--driver bridge桥接 #--subnet 192.168.0.0/16子网,16位 192.168.0.2~192.168.255.255 #--gateway 192.168.0.1网关 docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet docker network ls docker network inspect mynet #用自定义的网络,默认就不走docker01了 docker run -d -P --name tomcat01 --net mynet tomcat docker run -d -P --name tomcat02 --net mynet tomcat #可以看到自定义网络里的两个tomcat容器 docker network inspect mynet #测试 docker exec -it tomcat01 ping 192.168.0.3 #--link不支持名字(容器重启IP就会变),自定义的支持 docker exec -it tomcat01 ping tomcat02
好处:redis,mysql等不同的集群,各自的集群使用自己的网络可以保证集群的安全和健康,网络之间是相互隔离的
redis集群 192.160.0.0
MySQL集群 192.161.0.0
两个网络是相互隔离的,也可以打通,叫网络联通
网络连通docker network --help docker network connect --help #tomcat01容器链接到mynet网络 docker network connect mynet tomcat01 #containers里就有了tomcat01,也就是一个容器两个IP docker network mynet inspect #结论:需要跨网络操作就需要docker network connect连通redis集群搭建
#创建redis网络
docker network create redis --subnet 172.38.0.0/16
docker network inspect redis
#创建6个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
#查看
cd /mydata/
ls
cd redis
ls
node-1 node-2 node-3 node-4 node-5 node-6
cd node-1
ls
cd conf/
ls
redis.conf
#启动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 16371: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
#脚本启动6个容器
docker run -p 637${port}:6379 -p 1637${port}:16379 --name redis-${port}
-v /mydata/redis/node-${port}/data:/data
-v /mydata/redis/node-${port}/conf/redis.conf:/etc/redis/redis.conf
-d --net redis --ip 172.38.0.1${port} redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf;
docker ps
docker exec -it redis-1 /bin/sh #阉割过的没有/bin/bash ,用sh
ls
nodes.conf appendonle.aof
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
yes
#-c集群 不加c就是单机redis,
redis-cli -c
cluster info
#存一个值
set a test
#停掉存值的容器
docker stop 容器id
#测试高可用
get a #master挂掉后slave顶上,需要一会时间
#查看具体信息
cluster nodes #会显示master fail,slave变成master
微服务打包Docker镜像
1.打jar包
jar存放位置
3.编写DockerFile
4.把jar包和DockerFile传到服务器
5.在构建成镜像直接run
如果镜像很多呢?
DOcker Compose Docker Swarm CI/CD之Jenkins


