前言:本文会以多个实际的线上例子,分享自己对于Docker和Podman的一点使用经验及踩过的坑,希望对读者有一点帮助。

本文bash脚本初步加工后可直接使用(兼容mac和linux系统),对于关键点会有注重说明,但是对于一些细节需要读者自行去查阅相关文档,这里不会具体展开。

一、部署Apollo

1、docker脚本

version=2.0.1
dbhost_port=host.docker.internal:3306
dbuser=root
dbpwd=xxxx docker stop apollo-configservice && docker rm apollo-configservice
docker stop apollo-adminservice && docker rm apollo-adminservice
docker stop apollo-portal && docker rm apollo-portal docker run -p 28080:8080 \
--init \
--add-host=host.docker.internal:host-gateway \
-v /etc/localtime:/etc/localtime:ro \
-e SPRING_DATASOURCE_URL="jdbc:mysql://$dbhost_port/ApolloConfigDB?characterEncoding=utf8" \
-e SPRING_DATASOURCE_USERNAME=$dbuser \
-e SPRING_DATASOURCE_PASSWORD=$dbpwd \
-e ENV=dev \
-e JAVA_OPTS='-Xmx128m -Xms128m' \
-d -v /tmp/logs:/opt/logs --name apollo-configservice apolloconfig/apollo-configservice:$version
sleep 30s docker run -p 28090:8090 \
--init \
--add-host=host.docker.internal:host-gateway \
--link apollo-configservice:apollo-configservice \
-v /etc/localtime:/etc/localtime:ro \
-e SPRING_DATASOURCE_URL="jdbc:mysql://$dbhost_port/ApolloConfigDB?characterEncoding=utf8" \
-e SPRING_DATASOURCE_USERNAME=$dbuser \
-e SPRING_DATASOURCE_PASSWORD=$dbpwd \
-e ENV=dev \
-e JAVA_OPTS='-Xmx128m -Xms128m' \
-d -v /tmp/logs:/opt/logs --name apollo-adminservice apolloconfig/apollo-adminservice:$version
sleep 30s docker run -p 28070:8070 \
--init \
--link apollo-configservice:apollo-configservice \
--add-host=host.docker.internal:host-gateway \
-v /etc/localtime:/etc/localtime:ro \
-e SPRING_DATASOURCE_URL="jdbc:mysql://$dbhost_port/ApolloPortalDB?characterEncoding=utf8" \
-e SPRING_DATASOURCE_USERNAME=$dbuser \
-e SPRING_DATASOURCE_PASSWORD=$dbpwd \
-e APOLLO_PORTAL_ENVS=dev,prd \
-e DEV_META=http://host.docker.internal:28080 \
-e PRD_META=http://host.docker.internal:28080 \
-e ENV=dev \
-e JAVA_OPTS='-Xmx128m -Xms128m' \
-d -v /tmp/logs:/opt/logs --name apollo-portal apolloconfig/apollo-portal:$version echo "apollo启动完成"

2、podman脚本

podman stop apollo-configservice && podman rm apollo-configservice
podman run -p 28080:8080 \
-d --rm \
-v /etc/localtime:/etc/localtime:ro \
-e SPRING_DATASOURCE_URL="jdbc:mysql://host.containers.internal:3306/ApolloConfigDB?characterEncoding=utf8" \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=xxxx \
-e ENV=dev \
-e JAVA_OPTS='-Xmx128m -Xms128m' \
--name apollo-configservice apolloconfig/apollo-configservice:2.0.1
sleep 30s podman stop apollo-adminservice && podman rm apollo-adminservice
podman run -p 28090:8090 \
-d --rm \
-v /etc/localtime:/etc/localtime:ro \
-e SPRING_DATASOURCE_URL="jdbc:mysql://host.containers.internal:3306/ApolloConfigDB?characterEncoding=utf8" \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=xxxx \
-e ENV=dev \
-e JAVA_OPTS='-Xmx128m -Xms128m' \
--name apollo-adminservice apolloconfig/apollo-adminservice:2.0.1
sleep 30s podman stop apollo-portal && podman rm apollo-portal
podman run -p 28070:8070 \
-d --rm\
-v /etc/localtime:/etc/localtime:ro \
-e SPRING_DATASOURCE_URL="jdbc:mysql://host.containers.internal:3306/ApolloPortalDB?characterEncoding=utf8" \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=xxxx \
-e APOLLO_PORTAL_ENVS=dev,prd \
-e DEV_META=http://host.containers.internal:28080 \
-e PRD_META=http://host.containers.internal:28080 \
-e ENV=dev \
-e JAVA_OPTS='-Xmx128m -Xms128m' \
--name apollo-portal apolloconfig/apollo-portal:2.0.1
sleep 30s
echo "apollo启动完成"

3、注意事项

  1. docker里面容器可以通过 host.docker.internal 来访问宿主机,而podman容器里面是通过 host.containers.internal 来访问宿主机,注意区分。

  2. docker里面可以通过 --link 参数来连接两个容器的网络,使得容器之间可以互相通过 --name 指定的容器名 + 端口来访问。但podman不行,即使显式指定 --hostname 也不行。podman两个容器之间只能通过 ip 地址来访问,可以用 --ip 参数显式指定ip。ip的网段是10.88.0.0/16,个数为2^16 - 2 = 65536 -2 = 65534个 。

  3. 对于第2条,在mac高版本上是不适用的(即容器之间可以通过hostname来访问),虽然翻遍了官方文档,也没找到支持的论据,只能怀疑是高版本的feature(linux podman版本4.4.1,mac podman版本4.8.3)。

  4. 不要使用docker-compose,自己写bash脚本更为灵活自主可控。

  5. podman和docke命令可以互相替换,一般来说podman已经内置了命令转换功能,如果没有的话,可以通过下面代码来实现在脚本中的命令互换(脚本跟命令行的实现方式不一样)

#!/bin/bash
# 参考链接:https://blog.51cto.com/u_15162069/2780080?articleABtest=1
# 已前置设置 alias docker=podman
shopt -s expand_aliases
source ~/.bash_profile
alias
# 使用which命令判断命令是否存在
if which docker >/dev/null 2>&1; then
echo "use docker"
else
echo "use podman replace docker"
docker -v
fi
# put your docker or podman command in here

二、部署kafka

1、docker脚本

docker stop zookeeper && docker rm zookeeper
# https://hub.docker.com/r/bitnami/zookeeper
docker run -d --name zookeeper \
-p 2181:2181 \
--network=common_container_network \
-v /home/data/docker/bitnami/zookeeper:/bitnami \
-e TZ=CST-8 \
-e ALLOW_ANONYMOUS_LOGIN=YES \
bitnami/zookeeper:3.9
sleep 5s docker stop kafka && docker rm kafka
docker run -d --name kafka \
-p 19092:19092 \
--network=common_container_network \
-v /home/data/docker/bitnami/kafka:/bitnami \
-e KAFKA_HEAP_OPTS='-Xmx512m -Xms512m' \
-e KAFKA_CFG_NODE_ID=0 \
-e TZ=CST-8 \
-e KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181 \
-e KAFKA_CFG_LISTENERS=INTERNAL://:9092,EXTERNAL://:127.0.0.1:19092 \
-e KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT \
-e KAFKA_CFG_ADVERTISED_LISTENERS=INTERNAL://:9092,EXTERNAL://127.0.0.1:19092 \
-e KAFKA_CFG_LISTENERS=INTERNAL://:9092,EXTERNAL://:19092 \
-e KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INTERNAL \
bitnami/kafka:3.4 sleep 20s docker stop kafka-exporter && docker rm kafka-exporter
docker run -d --name kafka-exporter \
--restart=no \
--network=common_container_network \
-u root \
-p 19308:19308 \
danielqsj/kafka-exporter:v1.7.0 \
--web.listen-address=:19308 \
--kafka.server=kafka:9092 \
--kafka.version=3.4.1

2、podman脚本

docker stop zookeeper && docker rm zookeeper
podman run -d --name=zookeeper --ip=10.88.222.1\
-p 2181:2181 \
-v /home/data/docker/bitnami:/bitnami \
-e TZ=CST-8 \
-e ALLOW_ANONYMOUS_LOGIN=YES \
bitnami/zookeeper:3.9
sleep 5s docker stop kafka && docker rm kafka
docker run -d --name=kafka --ip=10.88.222.2 \
-p 19092:19092 \
-v /home/data/docker/bitnami:/bitnami \
-e KAFKA_HEAP_OPTS='-Xmx512m -Xms512m' \
-e KAFKA_CFG_NODE_ID=0 \
-e TZ=CST-8 \
-e KAFKA_CFG_ZOOKEEPER_CONNECT=10.88.222.1:2181 \
-e KAFKA_CFG_LISTENERS=INTERNAL://:9092,EXTERNAL://:172.18.159.144:19092 \
-e KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT \
-e KAFKA_CFG_ADVERTISED_LISTENERS=INTERNAL://:9092,EXTERNAL://47.119.23.205:19092 \
-e KAFKA_CFG_LISTENERS=INTERNAL://:9092,EXTERNAL://:19092 \
-e KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INTERNAL \
bitnami/kafka:3.4
sleep 10s docker stop kafka-exporter && docker rm kafka-exporter
docker run -d --name kafka-exporter \
--restart=no \
-u root \
-p 19308:19308 \
danielqsj/kafka-exporter:v1.7.0 \
--web.listen-address=:19308 \
--kafka.server=10.88.222.2:9092 \
--kafka.version=3.4.1

3、注意事项

  1. 注意bitnami的镜像都是rootless,但在笔者mac下,无论怎样做(已尽最大努力尝试,建议直接放弃),都不能实现文件的正确挂载。linux可以正常挂载。
  2. docker只有容器的概念,而podman里面有 容器Pod 的概念。多个容器可以在同一个pod,由pod统一管理端口映射,且pod里面容器共享网络,此时容器直接可以直接通过localhost + 端口来互相访问。
  3. 注意对于kafka的一些设置,KAFKA_CFG_ADVERTISED_LISTENERS 用于设置暴露在外网的连接地址,KAFKA_CFG_LISTENERS 用于设置暴露在内网的连接地址,这两个地址都会注册到zk上。
  4. kafka其实也可以不依赖zk,高版本已经内置KRaft(v2.8+),成熟度不详。
  5. --param 参数如果放在镜像名称之前,代表docker的参数设置,之后,则是对于镜像的参数设置。

三、部署Prometheus

1、docker脚本

docker stop prometheus && docker rm prometheus
# prometheus
docker run -d \
--restart=no \
-u root \
--name prometheus \
--network=common_container_network \
--add-host=host.docker.internal:host-gateway \
-p 19090:19090 \
-v /home/data/docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
-v /home/data/docker/prometheus/data:/prometheus \
-v /etc/localtime:/etc/localtime:ro \
prom/prometheus:v2.37.0 \
--storage.tsdb.retention.time=30d \
--storage.tsdb.path=/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--web.enable-lifecycle \
--web.listen-address=:19090 docker stop alertmanager && docker rm alertmanager
# alertmanager
docker run -d \
--restart=no \
-u root \
--name alertmanager \
--network=common_container_network \
--add-host=host.docker.internal:host-gateway \
-p 19093:19093 \
-v /home/data/docker/prometheus/alertmanager:/etc/prometheus/alertmanager \
-v /etc/localtime:/etc/localtime:ro \
prom/alertmanager:v0.25.0 \
--config.file=/etc/prometheus/alertmanager/alertmanager.yml \
--storage.path="/etc/prometheus/alertmanager" \
--data.retention=120h \
--web.listen-address=:19093 docker stop node-exporter && docker rm node-exporter
# node-exporter
docker run -d --name=node-exporter \
--restart=no \
-u root \
--network=common_container_network \
--add-host=host.docker.internal:host-gateway \
-p 19100:19100 \
-v "/proc:/host/proc" \
-v "/sys:/host/sys" \
-v "/:/rootfs" \
prom/node-exporter:v1.6.0 \
--path.rootfs=/host \
--web.listen-address=:19100 \
--path.procfs /host/proc --path.sysfs /host/sys \
--collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)"

2、podman脚本

docker stop prometheus && docker rm prometheus
docker run -d --rm \
--restart=no \
-u root \
--name prometheus \
-p 19090:19090 \
-v /home/data/docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml \
-v /home/data/docker/prometheus/data:/prometheus \
-v /etc/localtime:/etc/localtime:ro \
prom/prometheus:v2.37.0 \
--storage.tsdb.retention.time=30d \
--storage.tsdb.path=/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--web.enable-lifecycle \
--web.listen-address=:19090 docker stop alertmanager && docker rm alertmanager
docker run -d --rm \
--restart=no \
-u root \
--name alertmanager \
-p 19093:19093 \
-v /home/data/docker/prometheus/alertmanager:/etc/prometheus/alertmanager \
-v /etc/localtime:/etc/localtime:ro \
prom/alertmanager:v0.25.0 \
--config.file=/etc/prometheus/alertmanager/alertmanager.yml \
--storage.path="/etc/prometheus/alertmanager" \
--data.retention=120h \
--web.listen-address=:19093 docker stop node-exporter && docker rm node-exporter
docker run -d --name=node-exporter \
--restart=no \
-u root \
-p 19100:19100 \
-v "/proc:/host/proc" \
-v "/sys:/host/sys" \
-v "/:/rootfs" \
prom/node-exporter:v1.6.0 \
--path.rootfs=/host \
--web.listen-address=:19100 \
--path.procfs /host/proc --path.sysfs /host/sys \
--collector.filesystem.ignored-mount-points "^/(sys|proc|dev|host|etc)($|/)"

3、部署grafana

# docker和grafana可以混用
# 可以对配置文件进行充分定制
docker stop grafana && docker rm grafana
docker run -d --restart=no \
-u root \
--name=grafana \
-v /home/data/docker/grafana/grafana.ini:/etc/grafana/grafana.ini \
-p 13000:13000 \
-v /etc/localtime:/etc/localtime:ro \
grafana/grafana-enterprise:10.2.3 \
--config=/etc/grafana/grafana.ini

有一说一,grafana是真的香,功能是真的多。后面就直接使用grafana内置功能来做监控报表的数据展示了,不单独写UI界面了,敬请期待~

四、相关命令汇总

以下是一些可能会经常用到的命令,这里也简单列一下:

# 间接实现多行注释
if false; then
# 快速运行
docker run -d -p 19093:19093 --name alertmanager prom/alertmanager:v0.25.0
# 查看镜像详细信息
docker inspect grafana
# 进入镜像命令行
docker exec -it grafana sh
# 查看日志
docker logs grafana
# 查看容器详细信息
docker stats grafana
# 复制目录到远程服务器
scp -r /Users/huangkui/work/online/docker/apollo root@110.42.230.56:/home/data/docker
# 复制远程服务器文件到本地
scp -r root@110.42.230.56:/usr/lib/bin/jmap /Users/huangkui/work/xiaokui/docker/apollo/prd
# 从容器内部复制文件出来
docker cp 04b4dd7569cf:/apollo/scripts/startup.sh /Users/huangkui/work/docker/apollo
# 复制文件到容器内部去
docker cp /Users/huangkui/work/xiaokui/docker/apollo/jmap apollo:/usr/lib/jvm/jre/bin
# 重启服务 Prometheus
curl -XPOST http://localhost:19090/-/reload
# 重启服务 AlertManager
curl -XPOST http://localhost:19093/-/reload
# 输入指定字符到文件
echo "hello world" >> test.txt
# 修改文件夹所有者
sudo chown -R 1001:1001 /Users/huangkui/home/data/docker/bitnami
# 修改文件权限
sudo chmod -R 777 /Users/huangkui/home/data/docker/bitnami
# 停止然后移除容器,不建议使用--rm参数,当容器启动异常时会丢失日志信息
docker stop grafana && docker rm grafana
fi

五、一键部署脚本

暂未发现其必要性,待补充。

欢迎关注微信公众号:好看的HK,第一时间掌握Java最新黑科技,轻轻松松进大厂!

对于Docker和Podman的一点使用经验的更多相关文章

  1. Docker Vs Podman

    翻译自 Chetansingh 2020年4月24日的博文<Docker Vs Podman> [1] 容器化的一场全新革命是从 Docker 开始的,Docker 的守护进程管理着所有的 ...

  2. Docker 与 Podman 容器管理的比较

    翻译自 Paul Ferrill 2020年9月1日的文章<Compare Docker vs. Podman for container management> [1] Docker 和 ...

  3. openMP的一点使用经验【非原创】

    按照百科上说的,针对于openmp的编程,最简单的就是在开头加个#include<omp.h>,然后在后面的for上加一行#pragma omp parallel for即可,下面的是较为 ...

  4. openMP的一点使用经验

    最近在看多核编程.简单来说,由于现在电脑CPU一般都有两个核,4核与8核的CPU也逐渐走入了寻常百姓家,传统的单线程编程方式难以发挥多核CPU的强大功能,于是多核编程应运而生.按照我的理解,多核编程可 ...

  5. 关于图像读取函数imread()的一点使用经验,注意默认参数的赋值

    读入数字图像到数组,用CNN进行训练,发现关于图像读取的一个问题. 问题描述:读取灰度数字图像,在验证时发现存在错误,从图像到数组中的值不完全一样? main code as follows: int ...

  6. 关于 WinScp 的一点使用经验

    在嵌入式平台下 是,使用SSH登陆,可以使用WinScp提供的图形界面,支持拖拽,鼠标直接打开,甚是好用. 使用WinScp 登陆的方式有,Scp和sftp两种,之前一只用scp,但后来出现了如下错误 ...

  7. Podman and Buildah for Docker users

    转自:https://developers.redhat.com/blog/2019/02/21/podman-and-buildah-for-docker-users/ I was asked re ...

  8. 选择 podman 的理由, 以及它和 Kubernetes , Docker 的区别

    转载自https://zhuanlan.zhihu.com/p/506265757 前言 大家好,我是 Liangdi, podman 4.x 版本已经发布了, 我也从 docker 开始向 podm ...

  9. 下一代容器架构已出,Docker何去何处?看看这里的6问6答!!

    我猜很多人一看这个标题已经感觉很懵逼了,什么?下一代容器都出来了,我还没学Docker呢!!! 咳咳~~在这里我给大家做一个保证,下一代容器目前也只是各个公司在测试阶段,Github上面也有很多Iss ...

  10. Podman 快速入门

    今天在某云上新购一台云服务器,发现已经有了 CentOS8.2 官方镜像可选,出于对新鲜事物的好奇,我决定开始采用 CentOS8.2,即使我还没有为它的新特性做好准备. 我的应用主要以单机版容器为主 ...

随机推荐

  1. Android常用布局之LinearLayout线性布局和RealtiveLayout相对布局

    LinearLayout最常用的属性: id layout_width layout_height background 外边距:layout_margin:也是有好多方向 layout_margin ...

  2. #根号分治,动态规划#洛谷 5616 [MtOI2019]恶魔之树

    题目传送门 分析 最小公倍数最终一定会被表示成若干个质数指数幂的情况(1的情况就直接乘上二的次幂) 然后每个数的加入相当于对每个质数的指数取最大值,但是如果将每个质数的次数都表示出来状态数很多, 考虑 ...

  3. #并查集,单调栈#美团2018年CodeM大赛-决赛 C-Traffic

    题目 分析 首先如果枚举起点\(i\),点\(i\)到点\(j\)(i<j)的距离跳到点\(k\)(k<i)一定不优,所以可以先处理这种情况, 用单调栈维护\(dp\)单调递增,并且如果栈 ...

  4. Qt线程简单使用二:QObject~创建任务类

      需求: 点击QPushButton按钮,QLabel中的数字,不断累加,一直到999.   做法: 创建任务类,用来完成任务,创建子线程,将任务类放到子线程中,点击QPushButton后,先发送 ...

  5. Spring的事务管理方式编程式和声名式

    spring的事务管理方式: 一.声名式 二.编程式 事务:查询不会影响数据的改变,对于增删改必须进行事务的管理.如果没有事务管理spring也提供了默认传播方式REQUIRED 一.声名式事务管理( ...

  6. 看不懂来打我,vue3如何将template编译成render函数

    前言 在之前的 通过debug搞清楚.vue文件怎么变成.js文件 文章中我们讲过了vue文件是如何编译成js文件,通过那篇文章我们知道了,template编译为render函数底层就是调用了@vue ...

  7. 一、Unity调用Xcode封装方法(工程引用文件)

    1.Xcode新建Static Library 工程 (我起的名字是UnityExtend 可以在接下来的图中看到) 2.打包unity ios工程 unity打包ios 打出Xcode工程 3.打开 ...

  8. HarmonyOS极客松“上分秘籍”! 高手们顶峰相见!

      HarmonyOS 极客马拉松2023 火热进行中,我们期待与各位开发者相聚一起,践行极客精神,创造无限可能! 我们鼓励各位极客们自由组队,挥洒创意,用HarmonyOS 探索移动应用和服务的更多 ...

  9. Vue3 解构赋值失去响应式引发的思考

    前言 vue3发布以来经历两年风头正盛,现在大有和react 平分秋色的势头,我们知道他是基于proxy 实现响应式的能力, 解决了vue2所遗留下来的一些问题,同时也正由于proxy的特性,也提高了 ...

  10. shell编程实现用户循环输入

    如果你想在Shell脚本中实现一个循环判断用户输入是否正确,并根据情况决定是否退出系统,可以使用一个无限循环(如while true)和条件语句来实现. 以下是一个示例代码,用于演示这种情况: #!/ ...