跳转到内容

docker

1. 背景

  1. 虚拟化技术的发展;
  2. 基于虚拟化技术的扩展性应用;

2. 架构

dockeronlinux

1725685088427

Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroupnamespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7 版本以后开始去除 LXC,转而使用自行开发的 libcontainer,从 1.11 版本开始,则进一步演进为使用 runCcontainerd

runc 是一个 Linux 命令行工具,用于根据 OCI 容器运行时规范 创建和运行容器。 containerd 是一个守护程序,它管理容器生命周期,提供了在一个节点上执行容器和管理镜像的最小功能集。

Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。

1725685135928

2.1. Docker Daemon

2.2. Docker Client

2.3. todo

3. 概念

3.1. 镜像

Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

Docker 镜像本质上是一组文件系统,除了包含容器运行时所需要的程序、库、资源、配置等文件,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。 为了更好的复用、定制和扩展,镜像技术使用了分层存储技术,它的主要原理是:每一层构建完成后就不会发生改变,新的一层的构建内容只发生在当前层,后一层的构建可以依赖前一层,也就是说可以在前一层的基础上进行再构建。因此,构建镜像的最佳实践就是尽可能保证不添加任何不需要的内容。由此,也产生了 compose 技术。

1725685186337

3.2. 容器

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。也因为这种隔离的特性,很多人初学 Docker 时常常会混淆容器和虚拟机。

前面讲过镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层

容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者 绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。 数据卷的生存周期独立于容器,容器消亡,数据卷不会消亡。因此,使用数据卷后,容器删除或者重新运行之后,数据却不会丢失。

Docker 容器的本质是进程,这个进程拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。并且,多个容器运行时,能够相互隔离。 Docker 容器在运行时,实际上是以镜像为基础层,然后在它上面创建一个存储层,但这个存储层是无状态的,也就是说用户对容器的任何操作都不会被保留,可以理解为这个存储层只是一个媒介,用户对容器的读写都是通过这个媒介来完成的,并且用户产生的数据也是通过这个媒介直接操作数据卷或是绑定的宿主目录的。 思考:容器在运行时,为什么不采用在原有基础上再次添加一个存储分层?

  1. 如果采用再添加一个存储分层的方式,那么就会导致每次操作容器都会产生一个新的存储层,这就会使得单个容器占用的存储空间越来越大;
  2. 采用直接读写在数据卷或绑定的宿主目录的方式,也是遵循了“职责分离”的原则,此时就可以把容器看作是生产产品的工厂,而用户的数据就是这个工厂的产品,把工厂和产品分隔开,也有利于工厂的复用。

3.3. 仓库

镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry 就是这样的服务。

一个 Docker Registry 中可以包含多个 仓库(Repository);每个仓库可以包含多个 标签(Tag);每个标签对应一个镜像。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

我们可以使用公开服务,也可以使用私有服务。

由于某些原因,在国内访问这些服务可能会比较慢。

国内的一些云服务商提供了针对 Docker Hub 的镜像服务(Registry Mirror),这些镜像服务被称为 加速器

常见的有 阿里云加速器DaoCloud 加速器

3.4. 卷

3.5. 网络

3.6. 容器编排

4. 实践

  • centos 平台上的安装过程

5. 常用软件的安装

redis
md
```sh

docker pull redis

docker run -p 6379:6379 --name redis \
-v /mydata/redis/data:/data \
-v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf

docker update redis --restart=always

```
mysql
md

```
# 拉取镜像
docker pull mysql:5.7

# 把镜像中的配置文件拷贝到本地
docker cp mysql:/etc/mysql/my.cnf /mydata/mysql/conf/my.cnf

# 启动
docker run -p 3306:3306 --name mysql \
--restart always \
-v /mydata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-v /mydata/mysql/conf/my.cnf:/etc/mysql/my.cnf \
-v /etc/localtime:/etc/localtime \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7


// 拉取镜像
[root@home docker]# docker pull mysql:5.7

5.7: Pulling from library/mysql
72a69066d2fe: Pull complete 
93619dbc5b36: Pull complete 
99da31dd6142: Pull complete 
626033c43d70: Pull complete 
37d5d7efb64e: Pull complete 
ac563158d721: Pull complete 
d2ba16033dad: Pull complete 
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

// 安装 
[root@home docker]# docker run -p 3306:3306 --name mysql \
> -v /mnt/doc/docker/mysql/log:/var/log/mysql \
> -v /mnt/doc/docker/mysql/data:/var/lib/mysql \
> -v /mnt/doc/docker/mysql/conf:/etc/mysql \
> -e MYSQL_ROOT_PASSWORD=root \
> -d mysql:5.7
0a4457b1eac5dbfdba0f483db94aeb4fd42652d9f893094cf34daa0f4877116d
[root@home docker]# docker ps -a
CONTAINER ID   IMAGE       COMMAND                   CREATED         STATUS         PORTS                                                  NAMES
0a4457b1eac5   mysql:5.7   "docker-entrypoint.s…"   6 seconds ago   Up 5 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql
[root@home docker]# cd /mnt/doc/docker/
[root@home mysql]# cd conf/
[root@home conf]# ll
总用量 0

// 创建配置文件
[root@home conf]# vi my.cnf

[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
init_connect='SET collation_connection = utf8mb4_unicode_ci'
init_connect='SET NAMES utf8mb4'
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

// 重启mysql
[root@home conf]# docker restart mysql
mysql
[root@home conf]# docker ps
CONTAINER ID   IMAGE       COMMAND                   CREATED         STATUS          PORTS                                                  NAMES
0a4457b1eac5   mysql:5.7   "docker-entrypoint.s…"   6 minutes ago   Up 10 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql

// 设置开机自启
[root@home conf]# docker update mysql --restart=always
mysql

// 解决时间问题
[root@home conf]# docker exec -it mysql bash
root@0a4457b1eac5:/# date
Sat Oct  7 12:58:45 UTC 2023
root@0a4457b1eac5:/# ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
root@0a4457b1eac5:/# date
Sat Oct  7 20:58:57 CST 2023
root@0a4457b1eac5:/# exit
exit

// 最后重启
[root@home conf]# docker restart mysql
mysql

```

解决时间差8小时的问题

1. 在客户端输入 select now(); 发现查了8小时
2. 进入 mysql 服务端: docker exec -it mysql bash
3. 查看mysql服务端当前时间: date ,发现差了8小时
4. 直接修改时区为上海: ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ,再次输入 date,发现时间已经正常
5. 重启mysql服务端

#### 5.2.2. 主从分离

> 说明:
> 由于实验过程要求创建千万级别的数据,为了避免在主从同步的过程中出现问题。我们采用现在单例数据库上面上创建一个千万级数据,之后备份下来。再搭建三个数据库实例,之后把数据依次恢复到三个实例上,然后再建立主从关系,最后开启主从复制的过程。
> **当然如果不需要关注千万级数据,那么我们只需要依次创建三个实例,之后建立主从关系,最后开启主从复制过程即可。也就是只需要执行「执行创建过程」、「开启主从复制过程」两个步骤即可。**

##### 5.2.2.1. 生成千万级数据的备份SQL

```bash
// 把之前的单例mysql中已经生成的千万级数据备份成sql语句
docker exec mysql sh -c 'exec mysqldump --databases monomer_order -uroot -proot' > /mydata/backupsqls/mysql/monomer_order.sql

```

##### 5.2.2.2. 三个单例mysql的搭建过程

###### 5.2.2.2.1. master搭建过程

> 让主机的3307端口映射出去。注意: binlog_format 推荐使用row,具体参考【[这里](https://help.aliyun.com/document_detail/67809.html)】。

```bash
// 创建容器
docker run -p 3307:3306 --name mysql-master \
-v /mydata/mysql-master/log:/var/log/mysql \
-v /mydata/mysql-master/data:/var/lib/mysql \
-v /mydata/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

// 创建配置文件
vi /mydata/mysql-master/conf/my.cnf

[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
default-time_zone='+8:00'
server_id=100
log_bin=master-bin
binlog_format=ROW
slow-query-log-file=/var/log/mysql/slow-query.log
long_query_time=1

// 设置开机自启动,并重启
docker update mysql-master --restart=always
docker restart mysql-master

// 创建主从复制的用户信息
docker exec -it mysql-master /bin/bash
mysql -uroot -proot
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

flush privileges;


```

###### 5.2.2.2.2. slave01搭建过程

> 让主机的3308端口映射出去。

```bash
// 创建容器
docker run -p 3308:3306 --name mysql-slave01 \
-v /mydata/mysql-slave01/log:/var/log/mysql \
-v /mydata/mysql-slave01/data:/var/lib/mysql \
-v /mydata/mysql-slave01/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

// 创建配置文件
vi /mydata/mysql-slave01/conf/my.cnf

[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
default-time_zone='+8:00'
server_id=101
log_bin=slave01-bin
relay_log=mysql-relay-bin

// 设置开机自启动,并重启
docker update mysql-slave01 --restart=always
docker restart mysql-slave01

```

###### 5.2.2.2.3. slave02搭建过程

> 让主机的3309端口映射出去。

```bash
// 创建容器
docker run -p 3309:3306 --name mysql-slave02 \
-v /mydata/mysql-slave02/log:/var/log/mysql \
-v /mydata/mysql-slave02/data:/var/lib/mysql \
-v /mydata/mysql-slave02/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7

// 创建配置文件
vi /mydata/mysql-slave02/conf/my.cnf

[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
character-set-server=utf8mb4
default-time_zone='+8:00'
server_id=102
log_bin=slave01-bin
relay_log=mysql-relay-bin

// 设置开机自启动,并重启
docker update mysql-slave02 --restart=always
docker restart mysql-slave02

```

##### 5.2.2.3. 恢复数据到三个实例中

> 由于数据量很大,我们采用先恢复数据到库里面的方式,让三个数据库实例的数据保持一致,之后再进行主从复制。

```bash
docker exec -i mysql-master sh -c 'exec mysql -uroot -proot' < /mydata/backupsqls/mysql/monomer_order.sql
docker exec -i mysql-slave01 sh -c 'exec mysql -uroot -proot' < /mydata/backupsqls/mysql/monomer_order.sql
docker exec -i mysql-slave02 sh -c 'exec mysql -uroot -proot' < /mydata/backupsqls/mysql/monomer_order.sql

```

##### 5.2.2.4. 开启从数据库实例的主从复制过程
>
> 主要分两个步骤:
>
> 1. 记录主库的位置信息;
> 2. 设置从库与主库的通信的相关信息,并在主库中开启主从复制过程;

```bash

////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// 1. 获取master的数据位置
////////////////////////////////////////////////////////////////////////////////////////////////////
docker exec -it mysql-master /bin/bash
mysql -uroot -proot
show master status;


////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// 2. 配置slave01
////////////////////////////////////////////////////////////////////////////////////////////////////
// 1. 进入slave01内部命令行
docker exec -it mysql-slave01 /bin/bash
mysql -uroot -proot

// 2. 设置主从复制的起始位置
CHANGE MASTER TO MASTER_HOST='192.168.1.150',MASTER_USER='slave',MASTER_PASSWORD='123456', \
MASTER_PORT=3307,MASTER_LOG_FILE='master-bin.000005',MASTER_LOG_POS=145291152;

// 3. 开始主从复制,并查看主从复制的状态
start slave;
show slave status\G

////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// 3. 配置slave02
////////////////////////////////////////////////////////////////////////////////////////////////////
// 1. 进入slave02内部命令行
docker exec -it mysql-slave02 /bin/bash
mysql -uroot -proot


// 2. 设置主从复制的起始位置
CHANGE MASTER TO MASTER_HOST='192.168.1.150',MASTER_USER='slave',MASTER_PASSWORD='123456', \
MASTER_PORT=3307,MASTER_LOG_FILE='master-bin.000005',MASTER_LOG_POS=145291152;

// 3. 开始主从复制,并查看主从复制的状态
start slave;
show slave status\G

////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// 4. 测试并验证
////////////////////////////////////////////////////////////////////////////////////////////////////
// 成功!!!done!!!

```
nexus
md
```sh
docker pull sonatype/nexus3

mkdir -p /mydata/nexus/data
chmod 777 -R /mydata/nexus

docker run -d --name nexus -p 8081:8081 \
--restart always \
-v /mydata/nexus/data:/nexus-data sonatype/nexus3

# 查看日志,看是否启动完成
docker logs -f nexus

# 启动后,查看自动生成的admin的密码
cat /mydata/nexus/data/admin.password

# 浏览器访问,然后登陆,用户名admin
修改密码: root1003 
设置为可以匿名访问

```
rocketmq
md
```sh
https://blog.csdn.net/qq_28410283/article/details/115855940
https://juejin.cn/post/7045944869642043422

# 使用docker安装
https://github.com/apache/rocketmq-docker


## 在mac上下载
git clone https://github.com/apache/rocketmq-docker.git

## 上传到服务器上
scp -r rocketmq-docker root@192.168.1.150:/home/resource


## 在服务器上打开,并执行
cd image-build
sh build-image.sh 4.5.0 centos
sh build-image-dashboard.sh 1.0.0 centos


## 创建docker挂载的卷
mkdir -p /mydata/rocketmq/data/namesrv/logs \
/mydata/rocketmq/data/namesrv/store \
/mydata/rocketmq/data/broker/logs \
/mydata/rocketmq/data/broker/store \
/mydata/rocketmq/etc/broker

## 创建配置文件
vi /mydata/rocketmq/etc/broker/broker.conf

brokerClusterName = DefaultCluster
brokerName = broker-a
brokerId = 0
deleteWhen = 04
fileReservedTime = 48
brokerRole = ASYNC_MASTER
flushDiskType = ASYNC_FLUSH
# Docker环境需要设置成宿主机IP
#brokerIP1 = {docker宿主机IP}
brokerIP1 = 192.168.56.10

## 创建compose构建文件的目录
mkdir /mydata/rocketmq/docker-compose

## 创建compose文件,【注意】,创建之前需要先查看一下上面操作步骤构建的镜像及其版本,不同时期的版本不一样,需要保持compose文件中的镜像版本与自己构建的版本的一致性;
vi docker-compose.yml

version: '3'
services:
  #Service for nameserver
  namesrv:
    image: apache/rocketmq:4.5.0
    container_name: rmqnamesrv
    restart: always
    ports:
      - 9876:9876
    volumes:
      - /mydata/rocketmq/data/namesrv/logs:/root/logs
    command: sh mqnamesrv

  #Service for broker
  broker:
    image: apache/rocketmq:4.5.0
    container_name: rmqbroker
    restart: always
    links:
      - namesrv
    depends_on:
      - namesrv
    ports:
      - 10909:10909
      - 10911:10911
      - 10912:10912
    volumes:
      - /mydata/rocketmq/data/broker/logs:/home/rocketmq/logs
      - /mydata/rocketmq/data/broker/store:/home/rocketmq/store
      - /mydata/rocketmq/etc/broker/broker.conf:/home/rocketmq/conf/broker.conf
    command: sh mqbroker -c /home/rocketmq/conf/broker.conf

  #Service for rocketmq-dashboard
  dashboard:
    image: apache/rocketmq-dashboard:1.0.0-centos
    container_name: rmqdashboard
    restart: always
    ports:
      - 8080:8080
    links:
      - namesrv
    depends_on:
      - namesrv
    environment:
      - NAMESRV_ADDR=namesrv:9876

## 启动
cd /mydata/rocketmq/docker-compose
docker-compose up -d

## 验证

http://192.168.1.150:8080/#/
```
rabbitmq
md

``` sh

docker search rabbitmq

docker pull rabbitmq

mkdir -p /mydata/rabbimq/

docker run -p 5672:5672 -p 15672:15672 --name rabbitmq \
-v /mydata/rabbitmq:/var/lib/rabbitmq \
-v /mydata/rabbitmq/logs:/var/log/rabbitmq \
-e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin \
-e RABBITMQ_LOG_BASE=/var/log/rabbitmq \
-d rabbitmq

docker exec -it rabbitmq /bin/bash

rabbitmq-plugins enable rabbitmq_management

## 开机自启动
docker update rabbitmq --restart=always


```

![image.png](./rabbitmq.snippet/image/1726243665825.png)
sentinel
md
```sh

docker pull bladex/sentinel-dashboard:1.7.1

docker run --name sentinel -p 8858:8858 -d bladex/sentinel-dashboard:1.7.1

docker update sentinel --restart=always

```
nginx
md
```sh

docker run -p 80:80 -p 443:443 --name nginx \
-v /mnt/e/backup/html:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx


docker update nginx --restart=always

```

![安装nginx](./nginx.snippet/image/1726243717228.png)

```

需求: 下载了极客时间的课程,每一套课程里面的每一课都有mp3、pdf、html三种文件,复制到服务器上的挂载的ntfs硬盘上了,
现在想要在mac电脑上访问这些html,最好是能够显示目录。

实现思路:使用ng作为文件服务器;

实现过程:
docker pull nginx
docker run -p 80:80 --name nginx -d nginx
docker container cp nginx:/etc/nginx /mydata/nginx/conf
mv /mydata/nginx/conf/nginx/* /mydata/nginx/conf
rm -rf /mydata/nginx/conf/nginx

docker stop nginx
docker rm nginx


下面一步很重要,把/mnt/e/backup/html映射出去
docker run -p 80:80 -p 443:443 --name nginx \
-v /mnt:/usr/share/nginx/html \
-v /mydata/nginx/logs:/var/log/nginx \
-v /mydata/nginx/conf:/etc/nginx \
-d nginx

docker update nginx --restart=always


再简单配置一下/mydata/nginx/conf/conf.d/default.conf

location / {
    root   /usr/share/nginx/html;
    autoindex on;  # 开启目录文件列表
}

测试,done!


```

```
docker pull fraoustin/fancyindex

docker run -p 80:80 --name fancyindex \
-v /mnt:/share \
-d fraoustin/fancyindex 

docker update fancyindex --restart=always

docker run -d -e "CONTAINER_TIMEZONE=Europe/Paris" \
-e WEBUSER=myuser" -e "WEBPASSWORD=mypassword" \
-v /mnt:/share --name fancyindex -p 8080:80 fraoustin/fancyindex 

-e WEBUSER=root -e WEBPASSWORD=root \
-e COLOR=blue \

```
elasticsearch
md
```
mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
echo "http.host: 0.0.0.0" >> /mydata/elasticsearch/config/elasticsearch.yml

chmod -R 777 /mydata/elasticsearch/

docker pull elasticsearch:7.4.2

docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms1024m -Xmx2048m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2

docker update elasticsearch --restart=always

```
kinaba
md

```sh
docker pull kibana:7.4.2
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.1.150:9200 -p 5601:5601 \
-d kibana:7.4.2

docker update kibana --restart=always

```

[Centos7 下安装最新 ffmpeg](https://blog.csdn.net/smily77369/article/details/114926723)
[CentOS7安装ffmpeg](https://blog.csdn.net/fengguang54/article/details/118725400)

---

**上面的方式在实践过程中会发现缺少部分编解码器,是不够完全的。**
**根据 **[**a-schild**](https://github.com/a-schild)**/**[**jave2**](https://github.com/a-schild/jave2)**的思路,直接下载这个包下面的运行文件即可。**

**如,mac上直接下载**
**jave-nativebin-osxm1/src/main/resources/ws/schild/jave/nativebin/ffmpeg-aarch64-osx ,**
**下载到本地之后,然后配置一下环境变量即可。**

6. 参考

make it come true