diff --git a/agent-go/executor/AppFunction.go b/agent-go/executor/AppFunction.go index de738b7..6255acb 100644 --- a/agent-go/executor/AppFunction.go +++ b/agent-go/executor/AppFunction.go @@ -794,6 +794,14 @@ func (op *AgentOsOperator) deployIngress(funcArgs []string) (bool, []string) { result = append(result, "替换SUPREME信息") return false, result } + parseIP = net.ParseIP(funcArgs[3]) + if parseIP == nil { + return false, append(result, "ip args error !") + } + if !BasicReplace(k8sIngressYamlFile, "A1C1IP", funcArgs[3]) { + result = append(result, "替换A1C1IP信息") + return false, result + } if !BasicReplace(k8sIngressYamlFile, "A1C1JS", funcArgs[4]) { result = append(result, "替换A1C1JS信息") return false, result diff --git a/agent-go/rabbitmq/OctopusMessage.go b/agent-go/rabbitmq/OctopusMessage.go index 2f0d3b9..279b1cb 100644 --- a/agent-go/rabbitmq/OctopusMessage.go +++ b/agent-go/rabbitmq/OctopusMessage.go @@ -167,14 +167,19 @@ func statusOMHandler(octopusMessage *OctopusMessage) { return } + // OMessageStatusTypeEnum var statusRes string - if strings.HasPrefix(statusMessage.StatusType, "P") { + if strings.HasPrefix(statusMessage.StatusType, "PING") { // ping info statusRes = status.Ping() - } else { + } else if strings.HasPrefix(statusMessage.StatusType, "METRIC") { // metric info agentStatusString, _ := json.Marshal(status.ReportAppStatus()) statusRes = string(agentStatusString) + } else if strings.HasPrefix(statusMessage.StatusType, "INFO") { + + } else { + log.WarnF("[statusOMHandler] - error octopus status message type of %s", statusMessage.StatusType) } // 返回消息 diff --git a/agent-go/status/CPU.go b/agent-go/status/CPU.go index 710b5e7..0fdae21 100644 --- a/agent-go/status/CPU.go +++ b/agent-go/status/CPU.go @@ -3,28 +3,29 @@ package status import ( "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/load" + "time" ) -type CPUStatus struct { - NumCores int - CPUInfo []cpu.InfoStat - CPUPercent float64 - CPULoads *load.AvgStat - SystemLoads *load.AvgStat +type CPUMetric struct { + NumCores int + CPUPercent float64 + CPULoads *load.AvgStat } -func GetCPUStatus() (*CPUStatus, error) { +type CPUInfo struct { + CPUMetric + + CPUInfo []cpu.InfoStat +} + +func GetCPUMetric() (*CPUMetric, error) { + numCores, err := cpu.Counts(true) if err != nil { return nil, err } - cpuInfo, err := cpu.Info() - if err != nil { - return nil, err - } - - cpuPercent, err := cpu.Percent(0, false) + cpuPercent, err := cpu.Percent(time.Second, false) if err != nil { return nil, err } @@ -34,17 +35,42 @@ func GetCPUStatus() (*CPUStatus, error) { return nil, err } - systemLoads, err := load.Avg() + return &CPUMetric{ + NumCores: numCores, + CPUPercent: cpuPercent[0], + CPULoads: cpuLoads, + }, nil + +} + +func GetCPUInfo() (*CPUInfo, error) { + numCores, err := cpu.Counts(true) if err != nil { return nil, err } - return &CPUStatus{ - NumCores: numCores, - CPUInfo: cpuInfo, - CPUPercent: cpuPercent[0], - CPULoads: cpuLoads, - SystemLoads: systemLoads, + cpuPercent, err := cpu.Percent(time.Second, false) + if err != nil { + return nil, err + } + + cpuLoads, err := load.Avg() + if err != nil { + return nil, err + } + + infoStats, err := cpu.Info() + if err != nil { + return nil, err + } + + return &CPUInfo{ + CPUMetric: CPUMetric{ + NumCores: numCores, + CPUPercent: cpuPercent[0], + CPULoads: cpuLoads, + }, + CPUInfo: infoStats, }, nil } diff --git a/agent-go/status/CPU_test.go b/agent-go/status/CPU_test.go index 0183fb3..138f6b9 100644 --- a/agent-go/status/CPU_test.go +++ b/agent-go/status/CPU_test.go @@ -7,7 +7,7 @@ import ( ) func TestGetCPUStatus(t *testing.T) { - cpuStatus, err := GetCPUStatus() + cpuStatus, err := GetCPUMetric() if err != nil { return } @@ -20,3 +20,17 @@ func TestGetCPUStatus(t *testing.T) { fmt.Println(string(marshalIndent)) } + +func TestGetCPUInfo(t *testing.T) { + cpuInfo, err := GetCPUInfo() + if err != nil { + return + } + + marshalIndent, err := json.MarshalIndent(cpuInfo, "", " ") + if err != nil { + fmt.Printf("error") + } + + fmt.Println(string(marshalIndent)) +} diff --git a/agent-go/status/Disk_test.go b/agent-go/status/Disk_test.go index dbf191a..64215a1 100644 --- a/agent-go/status/Disk_test.go +++ b/agent-go/status/Disk_test.go @@ -10,7 +10,6 @@ func TestGetDiskStatus(t *testing.T) { ds := GetDiskStatus() fmt.Printf("Total: %v, Used: %v\n", ds.Total, ds.Used) - fmt.Printf("Logical Disks: %v\n", ds.LogicalDisk) marshalIndent, err := json.MarshalIndent(ds, "", " ") if err != nil { diff --git a/agent-go/status/Host.go b/agent-go/status/Host.go new file mode 100644 index 0000000..0e3898e --- /dev/null +++ b/agent-go/status/Host.go @@ -0,0 +1,22 @@ +package status + +import ( + "github.com/shirou/gopsutil/v3/host" +) + +type HostInfo struct { + host.InfoStat +} + +func GetHostInfo() (*HostInfo, error) { + + info, err := host.Info() + if err != nil { + log.ErrorF("get host info error => %v", err) + return nil, err + } + + return &HostInfo{ + InfoStat: *info, + }, nil +} diff --git a/agent-go/status/Host_test.go b/agent-go/status/Host_test.go new file mode 100644 index 0000000..fabde1d --- /dev/null +++ b/agent-go/status/Host_test.go @@ -0,0 +1,25 @@ +package status + +import ( + "fmt" + "testing" +) + +func TestGetHostInfo(t *testing.T) { + + hostInfo := HostInfo{} + + fmt.Printf("host info is %v\n", hostInfo) + fmt.Printf("host info type is %T\n", hostInfo) + fmt.Printf("host info address is %p\n", &hostInfo) + + fmt.Println() + + info, err := GetHostInfo() + if err != nil { + t.Errorf("get host info error is %v", err) + } + + fmt.Printf("get host info is %v\n", info) + fmt.Printf("get host info address is %p\n", &info) +} diff --git a/agent-go/status/Memory.go b/agent-go/status/Memory.go index 4f65d65..f770e81 100644 --- a/agent-go/status/Memory.go +++ b/agent-go/status/Memory.go @@ -5,29 +5,106 @@ import ( "github.com/shirou/gopsutil/v3/mem" ) -type MemoryStatus struct { - TotalMemory uint64 - UsedMemory uint64 - AvailableMemory uint64 - TotalVirtualMemory uint64 - UsedVirtualMemory uint64 +type MemoryMetric struct { + TotalMemory uint64 + AvailableMemory uint64 + UsedMemory uint64 + UsedPercent float64 `json:"usedPercent"` + FreeMemory uint64 `json:"free"` } -func GetMemoryStatus() (*MemoryStatus, error) { - memoryStatus := &MemoryStatus{} +type MemoryInfo struct { + MemoryMetric + Buffers uint64 `json:"buffers"` + Cached uint64 `json:"cached"` + WriteBack uint64 `json:"writeBack"` + Dirty uint64 `json:"dirty"` + WriteBackTmp uint64 `json:"writeBackTmp"` + Shared uint64 `json:"shared"` + Slab uint64 `json:"slab"` + Sreclaimable uint64 `json:"sreclaimable"` + Sunreclaim uint64 `json:"sunreclaim"` + PageTables uint64 `json:"pageTables"` + SwapCached uint64 `json:"swapCached"` + CommitLimit uint64 `json:"commitLimit"` + CommittedAS uint64 `json:"committedAS"` + HighTotal uint64 `json:"highTotal"` + HighFree uint64 `json:"highFree"` + LowTotal uint64 `json:"lowTotal"` + LowFree uint64 `json:"lowFree"` + SwapTotal uint64 `json:"swapTotal"` + SwapFree uint64 `json:"swapFree"` + Mapped uint64 `json:"mapped"` + VmallocTotal uint64 `json:"vmallocTotal"` + VmallocUsed uint64 `json:"vmallocUsed"` + VmallocChunk uint64 `json:"vmallocChunk"` + HugePagesTotal uint64 `json:"hugePagesTotal"` + HugePagesFree uint64 `json:"hugePagesFree"` + HugePagesRsvd uint64 `json:"hugePagesRsvd"` + HugePagesSurp uint64 `json:"hugePagesSurp"` + HugePageSize uint64 `json:"hugePageSize"` +} + +func GetMemoryStatus() (*MemoryMetric, error) { + virtualMemoryStat, err := mem.VirtualMemory() + if err != nil { + return nil, err + } + + return &MemoryMetric{ + TotalMemory: virtualMemoryStat.Total, + AvailableMemory: virtualMemoryStat.Available, + UsedMemory: virtualMemoryStat.Used, + UsedPercent: virtualMemoryStat.UsedPercent, + FreeMemory: virtualMemoryStat.Free, + }, nil + +} + +func GetMemoryInfo() (*MemoryInfo, error) { virtualMemoryStat, err := mem.VirtualMemory() if err != nil { - return memoryStatus, err + return nil, err } - memoryStatus.TotalMemory = virtualMemoryStat.Total - memoryStatus.UsedMemory = virtualMemoryStat.Used - memoryStatus.AvailableMemory = virtualMemoryStat.Available - memoryStatus.TotalVirtualMemory = virtualMemoryStat.Total - memoryStatus.UsedVirtualMemory = virtualMemoryStat.Used - - return memoryStatus, nil + return &MemoryInfo{ + MemoryMetric: MemoryMetric{ + TotalMemory: virtualMemoryStat.Total, + AvailableMemory: virtualMemoryStat.Available, + UsedMemory: virtualMemoryStat.Used, + UsedPercent: virtualMemoryStat.UsedPercent, + FreeMemory: virtualMemoryStat.Free, + }, + Buffers: virtualMemoryStat.Buffers, + Cached: virtualMemoryStat.Cached, + WriteBack: virtualMemoryStat.WriteBack, + Dirty: virtualMemoryStat.Dirty, + WriteBackTmp: virtualMemoryStat.WriteBackTmp, + Shared: virtualMemoryStat.Shared, + Slab: virtualMemoryStat.Slab, + Sreclaimable: virtualMemoryStat.Sreclaimable, + Sunreclaim: virtualMemoryStat.Sunreclaim, + PageTables: virtualMemoryStat.PageTables, + SwapCached: virtualMemoryStat.SwapCached, + CommitLimit: virtualMemoryStat.CommitLimit, + CommittedAS: virtualMemoryStat.CommittedAS, + HighTotal: virtualMemoryStat.HighTotal, + HighFree: virtualMemoryStat.HighFree, + LowTotal: virtualMemoryStat.LowTotal, + LowFree: virtualMemoryStat.LowFree, + SwapTotal: virtualMemoryStat.SwapTotal, + SwapFree: virtualMemoryStat.SwapFree, + Mapped: virtualMemoryStat.Mapped, + VmallocTotal: virtualMemoryStat.VmallocTotal, + VmallocUsed: virtualMemoryStat.VmallocUsed, + VmallocChunk: virtualMemoryStat.VmallocChunk, + HugePagesTotal: virtualMemoryStat.HugePagesTotal, + HugePagesFree: virtualMemoryStat.HugePagesFree, + HugePagesRsvd: virtualMemoryStat.HugePagesRsvd, + HugePagesSurp: virtualMemoryStat.HugePagesSurp, + HugePageSize: virtualMemoryStat.HugePageSize, + }, nil } func FormatMemorySize(size uint64) string { diff --git a/agent-go/status/Memory_test.go b/agent-go/status/Memory_test.go index baa2a61..30024b3 100644 --- a/agent-go/status/Memory_test.go +++ b/agent-go/status/Memory_test.go @@ -14,10 +14,31 @@ func TestGetMemoryStatus(t *testing.T) { } fmt.Printf("Total Memory: %s\n", FormatMemorySize(memoryStatus.TotalMemory)) - fmt.Printf("Used Memory: %s\n", FormatMemorySize(memoryStatus.UsedMemory)) fmt.Printf("Available Memory: %s\n", FormatMemorySize(memoryStatus.AvailableMemory)) - fmt.Printf("Total Virtual Memory: %s\n", FormatMemorySize(memoryStatus.TotalVirtualMemory)) - fmt.Printf("Used Virtual Memory: %s\n", FormatMemorySize(memoryStatus.UsedVirtualMemory)) + fmt.Printf("Used Memory: %s\n ", FormatMemorySize(memoryStatus.UsedMemory)) + fmt.Printf("UsedPercent: %.2f %%\n", memoryStatus.UsedPercent) + fmt.Printf("Free Memory: %s\n", FormatMemorySize(memoryStatus.FreeMemory)) + + marshalIndent, err := json.MarshalIndent(memoryStatus, "", " ") + if err != nil { + fmt.Printf("error") + } + + fmt.Println(string(marshalIndent)) +} + +func TestGetMemoryInfo(t *testing.T) { + + memoryStatus, err := GetMemoryInfo() + if err != nil { + return + } + + fmt.Printf("Total Memory: %s\n", FormatMemorySize(memoryStatus.TotalMemory)) + fmt.Printf("Used Memory: %s\n", FormatMemorySize(memoryStatus.UsedMemory)) + fmt.Printf("Available Memory: %s\n", FormatMemorySize(memoryStatus.AvailableMemory)) + fmt.Printf("UsedPercent: %.2f %%\n", memoryStatus.UsedPercent) + fmt.Printf("Free Memory: %s\n", FormatMemorySize(memoryStatus.FreeMemory)) marshalIndent, err := json.MarshalIndent(memoryStatus, "", " ") if err != nil { diff --git a/agent-go/status/Network.go b/agent-go/status/Network.go index 06b67a3..e5c8500 100644 --- a/agent-go/status/Network.go +++ b/agent-go/status/Network.go @@ -2,12 +2,21 @@ package status import ( "fmt" + "github.com/go-openapi/errors" "github.com/shirou/gopsutil/v3/net" net2 "net" + "regexp" "strings" "time" ) +type NetworkMetric struct { + net.IOCountersStat + + SendSpeed float64 + RecvSpeed float64 +} + type NetworkStatus struct { Name string `json:"name,omitempty"` InternalIPv4 []string `json:"internal_ip_v4,omitempty"` @@ -21,6 +30,73 @@ type NetworkStatus struct { RecvRate string `json:"recv_rate,omitempty"` } +func GetNetworkMetric() ([]NetworkMetric, error) { + interfaceStatList, err := net.Interfaces() + if err != nil { + log.ErrorF("[GetNetworkMetric] - get interface list error %v\n", err) + return nil, err + } + contains := false + for _, interfaceStat := range interfaceStatList { + if MatchNetInterfaceRight(interfaceStat.Name) { + contains = true + break + } + } + if !contains { + msg := "[GetNetworkMetric]- can not find desired net interface !" + log.Warn(msg) + return nil, errors.New(233, msg) + } + + ioCountersStats, err := net.IOCounters(false) + if err != nil { + log.ErrorF("[GetNetworkMetric] - get io counter list error %v\n", err) + return nil, err + } + + duration := time.Second * 2 + time.Sleep(duration) + + afterIoCounterList, err := net.IOCounters(false) + if err != nil { + log.ErrorF("[GetNetworkMetric] - get io counter list second error %v\n", err) + return nil, err + } + + var result []NetworkMetric + + for _, interfaceStat := range interfaceStatList { + if MatchNetInterfaceRight(interfaceStat.Name) { + + for _, after := range afterIoCounterList { + if strings.Contains(after.Name, interfaceStat.Name) { + for _, before := range ioCountersStats { + if strings.Contains(before.Name, interfaceStat.Name) { + // match after and before interface + + // assign + networkMetric := NetworkMetric{ + IOCountersStat: after, + SendSpeed: 0, + RecvSpeed: 0, + } + + networkMetric.SendSpeed = (float64(after.BytesSent - before.BytesSent)) / duration.Seconds() + networkMetric.RecvSpeed = (float64(after.BytesRecv - before.BytesRecv)) / duration.Seconds() + + result = append(result, networkMetric) + } + } + } + } + + } + } + + return result, nil +} + func GetNetworkStatus() (*NetworkStatus, error) { interfaces, err := net.Interfaces() if err != nil { @@ -119,3 +195,18 @@ func GetInternelIpAddrs(addresses []string) ([]string, []string) { } return ipv4, ipv6 } + +func MatchNetInterfaceRight(interfaceName string) bool { + + match, _ := regexp.MatchString(`^(eth|enp|wlan|ens|eno)\d+`, interfaceName) + if match { + return true + } + + match, _ = regexp.MatchString(`^(lo)`, interfaceName) + if match { + return true + } + + return match +} diff --git a/agent-go/status/Network_test.go b/agent-go/status/Network_test.go index b3d3ffd..3fe3090 100644 --- a/agent-go/status/Network_test.go +++ b/agent-go/status/Network_test.go @@ -20,3 +20,27 @@ func TestGetNetworkInfo(t *testing.T) { fmt.Println(string(marshalIndent)) } + +func TestMatchNetInterfaceRight(t *testing.T) { + interfaceNames := []string{"eth0", "eth1", "enp3s0", "wlan0", "lo", "ens12", "eno1", "asdas", "en0"} + + for _, name := range interfaceNames { + if MatchNetInterfaceRight(name) { + t.Logf("匹配到的网卡名称: %s\n", name) + } + } +} + +func TestGetNetworkMetric(t *testing.T) { + metric, err := GetNetworkMetric() + if err != nil { + t.Logf("get network metric error %s\n", err.Error()) + } + + for _, networkMetric := range metric { + fmt.Println() + bytes, _ := json.MarshalIndent(networkMetric, "", " ") + fmt.Println(string(bytes)) + fmt.Println() + } +} diff --git a/agent-go/status/Status.go b/agent-go/status/Status.go index 36f14ed..3dad063 100644 --- a/agent-go/status/Status.go +++ b/agent-go/status/Status.go @@ -21,8 +21,8 @@ type StatusMessage struct { } type AgentStatus struct { - CPUStatus *CPUStatus - MemoryStatus *MemoryStatus + CPUStatus *CPUMetric + MemoryStatus *MemoryMetric NetworkStatus *NetworkStatus DiskStatus *DiskStatus } @@ -43,10 +43,9 @@ func Ping() string { return "PONG" } -// todo change to go model func ReportAppStatus() *AgentStatus { - cpuStatus, cpuerr := GetCPUStatus() + cpuStatus, cpuerr := GetCPUMetric() memoryStatus, memerr := GetMemoryStatus() networkStatus, neterr := GetNetworkStatus() if cpuerr != nil || memerr != nil || neterr != nil { diff --git a/server/src/main/java/io/wdd/func/auto/service/AppFuncScheduler.java b/server/src/main/java/io/wdd/func/auto/service/AppFuncScheduler.java index 99302b6..c978cbb 100644 --- a/server/src/main/java/io/wdd/func/auto/service/AppFuncScheduler.java +++ b/server/src/main/java/io/wdd/func/auto/service/AppFuncScheduler.java @@ -24,7 +24,7 @@ public class AppFuncScheduler { /** * 参数固定顺序为 A1C2IP SUPREME N1C2IP A1C1IP A1C1JS M2D2IP KIMMY JACLOVE - * 1 2 3 4 5 6 7 8 + * 1 2 3 4 5 6 7 8 * * @param projectDeployContext * @param projectInfoPO @@ -34,20 +34,20 @@ public class AppFuncScheduler { ArrayList appFuncArgs = new ArrayList<>(); appFuncArgs.add(projectDeployContext - .getMasterNode() - .getServerIpInV4()); + .getMasterNode() + .getServerIpInV4()); appFuncArgs.add(projectInfoPO.getProjectNamespace()); appFuncArgs.add(projectDeployContext - .getMasterNode() - .getServerIpInV4()); + .getMasterNode() + .getServerIpInV4()); appFuncArgs.add(projectDeployContext - .getMasterNode() - .getServerIpPbV4()); + .getMasterNode() + .getServerIpPbV4()); appFuncArgs.add(projectInfoPO.getProjectWebServicePort()); // M2D2IP appFuncArgs.add(projectDeployContext - .getMasterNode() - .getServerIpInV4()); + .getMasterNode() + .getServerIpInV4()); appFuncArgs.add(projectInfoPO.getProjectVersion()); // jackeyLoveFile appFuncArgs.add("init_5.1.0.tar"); @@ -106,9 +106,10 @@ public class AppFuncScheduler { AppFunctionEnum.DEPLOY_NFS, AppFunctionEnum.DEPLOY_TEST_NFS, AppFunctionEnum.DEPLOY_K8S_NAMESPACE, + AppFunctionEnum.DEPLOY_K8S_PVC, AppFunctionEnum.DEPLOY_K8S_MYSQL, AppFunctionEnum.DEPLOY_K8S_REDIS, - AppFunctionEnum.DEPLOY_K8S_PVC, + AppFunctionEnum.DEPLOY_K8S_MIDDLEWARES, AppFunctionEnum.DEPLOY_INGRESS // AppFunctionEnum.DEPLOY_FRONTEND // AppFunctionEnum.DEPLOY_BACKEND diff --git a/server/src/main/java/io/wdd/rpc/status/beans/OMessageStatusTypeEnum.java b/server/src/main/java/io/wdd/rpc/status/beans/OMessageStatusTypeEnum.java new file mode 100644 index 0000000..0d5bdf7 --- /dev/null +++ b/server/src/main/java/io/wdd/rpc/status/beans/OMessageStatusTypeEnum.java @@ -0,0 +1,28 @@ +package io.wdd.rpc.status.beans; + +public enum OMessageStatusTypeEnum { + + PING("PING", "检测Agent主机的将抗状况"), + + METRIC("METRIC", "检测Agent主机的Metric信息"), + + INFO("INFO", "检测Agent主机的详细硬件信息"); + + String statusTypeName; + + String statusDesc; + + + OMessageStatusTypeEnum(String statusTypeName, String statusDesc) { + this.statusTypeName = statusTypeName; + this.statusDesc = statusDesc; + } + + public String getStatusTypeName() { + return statusTypeName; + } + + public String getStatusDesc() { + return statusDesc; + } +} diff --git a/source/src/main/java/io/wdd/source/octopus/simple-middleware.yaml b/source/src/main/java/io/wdd/source/octopus/simple-middleware.yaml index 52cc834..354bc7a 100644 --- a/source/src/main/java/io/wdd/source/octopus/simple-middleware.yaml +++ b/source/src/main/java/io/wdd/source/octopus/simple-middleware.yaml @@ -47,22 +47,37 @@ services: volumes: - 'rabbitmq_data:/bitnami/rabbitmq/mnesia' redis: - # https://hub.docker.com/r/bitnami/redis - image: bitnami/redis:6.2.11-debian-11-r1 + image: redis/redis-stack:6.2.6-v10 networks: - app-tier - environment: - - REDIS_PASSWORD=boge8tingH - # Redis 6.0 features a new multi-threading model - - REDIS_IO_THREADS=4 - - REDIS_IO_THREADS_DO_READS=yes - - REDIS_PORT_NUMBER=6379 - - REDIS_REPLICATION_MODE=master - #- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL ports: - '21370:6379' + - '21371:8001' + environment: + # duration of 7 days + - REDISTIMESERIES_ARGS=DUPLICATE_POLICY LAST RETENTION_POLICY 604800000 + # Redis 6.0 features a new multi-threading model + #- REDIS_ARGS=protected-mode no masterauth boge8tingH appendonly yes + #- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL volumes: - - 'redis_data:/bitnami/redis/data' + - 'redis_data:/data' +# redis: +# # https://hub.docker.com/r/bitnami/redis +# image: bitnami/redis:6.2.11-debian-11-r1 +# networks: +# - app-tier +# environment: +# - REDIS_PASSWORD=boge8tingH +# # Redis 6.0 features a new multi-threading model +# - REDIS_IO_THREADS=4 +# - REDIS_IO_THREADS_DO_READS=yes +# - REDIS_PORT_NUMBER=6379 +# - REDIS_REPLICATION_MODE=master +# #- REDIS_DISABLE_COMMANDS=FLUSHDB,FLUSHALL +# ports: +# - '21370:6379' +# volumes: +# - 'redis_data:/bitnami/redis/data' volumes: mysql_data: