Docker
一、Docker 介绍
1.架构介绍
Docker 是一种容器化技术。
它类似于虚拟机,可以在里面运行程序。
只不过 Docker 使用的系统是最小的 Linux 内核。
相对于 Windows 虚拟机,Docker 占用的资源更少。
Docker 里面有两个重要的概念:镜像(Images)、容器(Containers)。
镜像可以理解成一个自定义的 Windows 的 ISO 文件,里面安装了需要运行的程序,它可以随便分享给任何人,人们安装到电脑上就可以启动系统。
容器就是运行的虚拟机,简单来说就是镜像(Images)安装到电脑上运行起来。一台电脑可以同时运行多个虚拟机,同理一个电脑上也可以运行多个容器。
每个容器拥有自己的系统,容器之间相互隔离,但是可以通信。
为了方便人们分享自己的容器,Docker 提供了一个镜像市场 DockerHub。
为了方便操作镜像和容器 Docker 开发了一套命令 Docker-cli。
2.Docker 安装
-
准备 Linux 环境
-
如果已经安装过需要卸载旧版 Docker 环境
yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine -
配置 yum 源
# 第一步:安装yum-utils工具 yum install -y yum-utils # 第二步:配置Docker的yum源 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo -
安装 Docker
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -
启动和校验
# 查看docker版本 docker -v # 启动Docker systemctl start docker # 查看docker进程是否正常启动 docker images # 停止Docker systemctl stop docker # 重启 systemctl restart docker # 设置开机自启 systemctl enable docker # 执行docker ps命令,如果不报错,说明安装启动成功 docker ps
3.配置镜像加速
#第一步:
sudo mkdir -p /etc/docker
#第二步:
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["加速器地址"]
}
EOF
#第三步:
sudo systemctl daemon-reload
#第四步:
sudo systemctl restart docker
二、Docker 命令
1.基本命令
说明:
[]中的内容表示可选操作
| 类型 | 操作 | 命令 | 说明 | 案例 |
|---|---|---|---|---|
| 镜像操作 | 查找镜像 | docker search | #查找 nginx 镜像docker search nginx | |
| 下载镜像 | docker pull 镜像名[:版本号] | 版本号可以省略,不加版本号默认下载最新的镜像 | #下载 nginx 镜像docker pull nginxdocker pull nginx:1.26.0 | |
| 查看本地下载的镜像 | docker images | #查看当前系统下载的镜像docker images | ||
| 删除本地下载的镜像 | docker rmi | 可以通镜像名删除,也可以通过镜像 id 删除 | #删除刚下载的镜像docker rmi nginx:1.26.0 | |
| 查看镜像详情 | docker image inspect | #查看刚刚下载的镜像详情docker image inspect myimage | ||
| 容器操作 | 运行容器 | docker run | 其他参数要写到 run 和镜像名的中间 | #创建并运行 nginx 容器docker run [其他参数] nginx |
| 查看运行中的容器 | docker ps [-a] | -a 参数:可以查看所有容器,包括停止的 | #查看启动中的容器信息docker ps | |
| 停止容器 | docker stop | #停止 nginxdocker stop nginx | ||
| 启动容器 | docker start | 可以启动停止的容器 | #启动 nginxdocker start nginx | |
| 重启容器 | docker restart | #重启 nginxdocker restart nginx | ||
| 查看容器状态 | docker stats | #查看 nginx 容器的占用信息docker stats nginx | ||
| 查看容器日志 | docker logs | #查看 nginx 容器的运行日志docker logs nginx | ||
| 进入容器内部 | docker exec | -it 参数:以交互模式进入 | #以交互模式进入 nginx 容器docker exec -it nginx bash | |
| 删除容器 | docker rm | -f 参数:强制删除 | #删除 nginx 容器docker rm nginx | |
| 查看容器信息 | docker inspect | #4.查看容器基本信息docker inspect 容器名 | ||
| 镜像打包 | 提交镜像 | docker commit | 在容器当前状态下创建一个新镜像 | #将修改的 nginx 容器打包成一个新的镜像docker commit -m "描述内容" 容器名 自定义镜像名:自定义版本号 |
| #保存镜像# | docker save | 将文件导出为本地文件(-o 参数:将文件打包成 tar 包) | #将镜像打包成 tar 包docker save -o 自定义文件名.tar 镜像名 | |
| #加载镜像# | docker load | 将别人打的压缩包加载成镜像 | #将刚才打成的 tar 包加载为本地镜像docker load -i 自定义文件名.tar | |
| 镜像发布 | 登录社区 | docker login | ||
| 镜像命名 | docker tag | dockerhub 的镜像都是用户名/镜像名因此要符合规则 | #给镜像命名docker tag 镜像名[:版本号] 用户名/新镜像名[:版本号] | |
| 推送 | docker push | #将镜像推送上去docker push 用户名/新镜像名[:版本号] |
2.run 命令详解
#1.基本用法 说明:[]中的内容可以省略
docker run [参数] 容器名[:版本号]
#2.参数详解
-d :后台运行
--name :给容器命名
-p :端口映射(本机端口:容器端口)
--restart always :开机启动
-e :设置环境变量
-v :目录挂载/数据卷挂载
--network :指定网络
#完整案例:启动最新的nginx镜像,将本机的1188端口映射到宿主机的88端口
docker run
-d
--name myNginx
-p 1188:80
nginx
三、Doceker 存储
Docker 容器与本机文件的交互方式有两种:
- 卷映射:容器中的文件映射到本机
- 目录挂载:本机文件或目录映射到容器内
卷映射与目录挂载在使用中的区别:
- 使用目录挂载的时候本地目录以
./或/开始。使用卷映射的时候不以./或/开始。- 数据卷仅可以在使用
docker run的时候挂载总结:目录挂载更方便
1. 目录挂载
将本地文件或目录映射到容器内部,本地目录中的内容修改,容器中会同步修改
注意事项:
- 目录挂载必须要以
./ 或/ 开始开头,否则会被认为成数据卷挂载- 目录挂载命令只能在创建容器时执行,如果容器已经创建了,就没法挂载了
#作用:将本地目录映射到容器内某个目录
-v 本地目录:容器内目录
#案例:将本地/app/nghtml目录映射到容器中的/usr/share/nginx/html中
docker run
-d
-v /app/nghtml:/usr/share/nginx/html
-p 80:80
--name myNgin
nginx
2.卷映射
将容器中的文件映射到本机,本机修改文件,容器中的文件会同步修改。
映射卷挂载后默认存放在本机
/var/lib/docker/volumes/<自定义卷名>下(windows 存放到哪里自己查)注意事项:
- 挂载数据卷命令只能在创建容器时执行,如果容器已经创建了,就没法挂载了
- 数据卷名字随便起
- 如果挂载的时候数据卷不存在,则会自动创建
- 直接删除容器,数据卷和里面的数据依旧会存在
#作用:将容器中的目录映射到本地
-v 自定义卷名:容器内的目录
#案例:将容器中的/etc/nginx映射到ngconf卷中
#(挂载完成后到本机的/var/lib/docker/volumes/<自定义卷名>下查看)
docker run
-d
-v nginx:/etc/nginx
-p 80:80
--name myNgin
nginx
#补充:
#1.查看所有的卷
docker volume ls
#2.创建卷
docker volume create 卷名
#3.查看卷的信息
docker volume inspect 卷名
3.头脑风暴
问:如果一个容器已经使用
docker run运行了,我该怎么挂载卷或进行目录映射?
1.停止容器:docker stop my-container
2.提交容器状态docker commit my-container my-new-image
3.使用 docker run 重新启动提交的容器,并额外添加你需要的 -v 或 --mount 参数来指定新的卷或绑定挂载。
4.删除旧的容器(如果不需要了)
四、Docker 网络
Docker 网路主要介绍:Docker 容器之间如何相互通信
Docker 默认网络机制:所有的容器都会加入
docker0网络,并分配一个唯一 ip 地址,因此他们可以通过容器内的 ip 互相访问。但是docker 0网络有一个缺点,不支持主机域名,只支持 ip 访问。而我们自己创建的 docker 网络可以通过主机域名访问,域名默认是容器的名字。因此我们可以通过创建自定义网络,实现容器之间通过容器名访问。
#常用命令
#1.创建网络
docker network create 网络名
#2.列举网络
docker network ls
#3.容器启动时加入指定网络
--network 创建的自定义网络名
#4.查看容器基本信息
docker inspect 容器名
#案例:创建一个网络,让两个容器都加入网络,并互相访问
#1.查看所有网络
docker network ls
#2.创建网络(后面的网络名随便起)
docker network create junqing
#3.容器加入
docker network connect junqing mysql
#4.新建容器,要求直接加入junqing网络
docker run -d --name junqing-oa -p 8080:8080 --network junqing oa
docker run -d --name mysql -p 3306:3306 --network junqing mysql
#5.进入mysql容器,通过容器名访问oa容器
curl http://oa:8080
五、环境变量
容器启动时需要指定的参数,通常镜像仓库的文档中会给出
#语法:-e key=value
#说明:一个-e只能指定一个环境变量,如果需要指定多个环境变量可以设置多个-e
#案例:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql
六、Docker Compose
前面启动容器的时候都是一个一个启动,可是我们上线项目的时候需要上线十几个服务,一个一个启动太慢了。为了解决这个问题,可以使用 Docker Compose,编写好启动信息,到时候无论在任何环境都能快速启动文件内的所有容器
1.常用命令
#上线(指第一次启动)
#说明:[]中的内容可以省略,默认启动当前目录下的compose.yaml文件
docker compose [-f yaml文件] up -d
#下线
docker compose [-f yaml文件] down [其他参数]
#启动(非第一次启动)
docker compose start x1 x2 x3
#停止
docker compose stop x1 x2 x3
#扩容(让某个容器多启动几个)
docker compose scale x1 x2 x3
2.Compose文件
Compose文件是
yaml格式的,在书写的时候需要定义几种常用的属性:
-
name:应用名(给本次启动起一个名字)-
services:服务配置(可以是多个服务,如:MySQL、Nginx)-
networks 网络-
volumes:卷映射(卷映射需要单独声明、目录挂载不需要单独声明)-
configs 配置-
secrets 密钥
3.案例
#案例:使用compose启动多个容器,服务包括mysql、wordpress
#第一步:编辑Compose文件
#给本次启动起一个名字
name: myblog
#需要启动的服务及其配置
services:
#mysql服务相关配置
mysql:
#容器名
container_name: mysql
#镜像
image: mysql:8.0
#端口
ports:
- 3306:3306
#环境变量[数组写法一]
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
#数据卷
volumes:
- mysql-data:/var/lib/mysql
- /app/myconf:/etc/mysql/conf.d
#启动策略
restart: always
networks:
- blog
#wordpress服务相关配置
wordpress:
#容器名
container_name: wordpress
#镜像
image: wordpress
#端口
ports:
- 8080:80
#环境变量[数组写法二]
environment:
WORDPRESS_DB_HOST: mysql
WORDPRESS_DB_USER: root
WORDPRESS_DB_PASSWORD: 123456
WORDPRESS_DB_NAME: wordpress
#数据卷
volumes:
- wordpress:/var/www/html
#启动策略
restart: always
networks:
- blog
#配置启动顺序(wordpress在mysql之后启动)
depends_on:
- mysql
#卷映射
volumes:
mysql-data:
wordpress:
#网络
networks:
blog:
#第二步:使用Compose启动容器
#中括号中的内容可以不写
docker compose [-f compose文件名] up -d
#第三步:我修改了部分配置内容,容器该怎么更新?只需要重新启动即可,只会变更修改的部分
#中括号中的内容可以不写
docker compose [-f compose文件名] up -d
#第四步:这个服务我不想用了怎么删除
#中括号中的内容意思是删除容器、网络、卷映射,不写默认不删除
docker compose [-f compose文件名] down [--rmi all -v]
七、DockerFile
我们自己写了一个项目,该怎么打包成镜像呢?这就用到了 DockerFile
1.常见参数
2.DockerFile
常用参数:
-
FROM:基础环境【可以是系统,如:centos。也可以是运行项目的版本,如:openjdk:17】-
LABEL:标签【相当于说明,随便写就行】-
COPY:将文件复制到镜像系统中-
ENTRYPOINT:指定启动命令- EXPOSE:暴露哪个端口
3.案例
#第一步:编辑Dockerfile文件
#基础运行环境 jdk8
FROM openjdk:8
#标签
LABEL 作者=123456
#复制文件到镜像 这里是将本地的app.jar复制到镜像系统根目录的app.jar中
COPY app.jar /app.jar
#指定启动命令
ENTRYPOINT java -jar /app.jar
#暴漏端口
EXPOSE 8080
#第二步:构建镜像【说明:最后一个点说明是在当前目录构建,非常重要】
#命令格式:docker build -f Dockerfile文件路径 -t 镜像名:版本号 .
docker build -f Dockerfile -t myimage:v1.0
#第三步:正常运行容器即可
八、Docker 综合案例
一键启动大型项目
-
由于有openserach因此需要提前操作一些命令
sudo swapoff -a sudo vi /etc/sysctl.conf vm.max_map_count=262144 sudo sysctl -p cat /proc/sys/vm/max_map_count -
创建docker compose文件
注意:需要修改kafuka中的ip配置,改成自己服务器的IP
name: devsoft services: redis: image: bitnami/redis:latest restart: always container_name: redis environment: - REDIS_PASSWORD=123456 ports: - '6379:6379' volumes: - redis-data:/bitnami/redis/data - redis-conf:/opt/bitnami/redis/mounted-etc mysql: image: mysql:8.0.31 restart: always container_name: mysql environment: - MYSQL_ROOT_PASSWORD=123456 ports: - '3306:3306' - '33060:33060' volumes: - mysql-conf:/etc/mysql/conf.d - mysql-data:/var/lib/mysql rabbit: image: rabbitmq:3-management restart: always container_name: rabbitmq ports: - "5672:5672" - "15672:15672" environment: - RABBITMQ_DEFAULT_USER=rabbit - RABBITMQ_DEFAULT_PASS=rabbit - RABBITMQ_DEFAULT_VHOST=dev volumes: - rabbit-data:/var/lib/rabbitmq - rabbit-app:/etc/rabbitmq opensearch-node1: image: opensearchproject/opensearch:2.13.0 container_name: opensearch-node1 environment: - cluster.name=opensearch-cluster - node.name=opensearch-node1 - discovery.seed_hosts=opensearch-node1,opensearch-node2 - cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2 - bootstrap.memory_lock=true - OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m - DISABLE_INSTALL_DEMO_CONFIG=true - DISABLE_SECURITY_PLUGIN=true ulimits: memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 volumes: - opensearch-data1:/usr/share/opensearch/data ports: - 9200:9200 - 9600:9600 opensearch-node2: image: opensearchproject/opensearch:2.13.0 container_name: opensearch-node2 environment: - cluster.name=opensearch-cluster - node.name=opensearch-node2 - discovery.seed_hosts=opensearch-node1,opensearch-node2 - cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2 - bootstrap.memory_lock=true - OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m - DISABLE_INSTALL_DEMO_CONFIG=true - DISABLE_SECURITY_PLUGIN=true ulimits: memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 volumes: - opensearch-data2:/usr/share/opensearch/data opensearch-dashboards: image: opensearchproject/opensearch-dashboards:2.13.0 container_name: opensearch-dashboards ports: - 5601:5601 expose: - "5601" environment: - OPENSEARCH_HOSTS=["http://opensearch-node1:9200","http://opensearch-node2:9200"] - DISABLE_SECURITY_DASHBOARDS_PLUGIN=true zookeeper: image: bitnami/zookeeper:3.9 container_name: zookeeper restart: always ports: - "2181:2181" volumes: - zookeeper_data:/bitnami environment: - ALLOW_ANONYMOUS_LOGIN=yes kafka: image: bitnami/kafka:3.4 container_name: kafka restart: always hostname: kafka ports: - '9092:9092' - '9094:9094' environment: - KAFKA_CFG_NODE_ID=0 - KAFKA_CFG_PROCESS_ROLES=controller,broker - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://0.0.0.0:9094 - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://192.168.110.110:9094 - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093 - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER - ALLOW_PLAINTEXT_LISTENER=yes - KAFKA_HEAP_OPTS=-Xmx512m -Xms512m volumes: - kafka-conf:/bitnami/kafka/config - kafka-data:/bitnami/kafka/data kafka-ui: container_name: kafka-ui image: provectuslabs/kafka-ui:latest restart: always ports: - 8080:8080 environment: - DYNAMIC_CONFIG_ENABLED=true - KAFKA_CLUSTERS_0_NAME=kafka-dev - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 volumes: - kafkaui-app:/etc/kafkaui nacos: image: nacos/nacos-server:v2.3.1 container_name: nacos ports: - 8848:8848 - 9848:9848 environment: - PREFER_HOST_MODE=hostname - MODE=standalone - JVM_XMX=512m - JVM_XMS=512m - SPRING_DATASOURCE_PLATFORM=mysql - MYSQL_SERVICE_HOST=nacos-mysql - MYSQL_SERVICE_DB_NAME=nacos_devtest - MYSQL_SERVICE_PORT=3306 - MYSQL_SERVICE_USER=nacos - MYSQL_SERVICE_PASSWORD=nacos - MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true - NACOS_AUTH_IDENTITY_KEY=2222 - NACOS_AUTH_IDENTITY_VALUE=2xxx - NACOS_AUTH_TOKEN=SecretKey012345678901234567890123456789012345678901234567890123456789 - NACOS_AUTH_ENABLE=true volumes: - /app/nacos/standalone-logs/:/home/nacos/logs depends_on: nacos-mysql: condition: service_healthy nacos-mysql: container_name: nacos-mysql image: nacos/mysql:8.0.30 environment: - MYSQL_ROOT_PASSWORD=root - MYSQL_DATABASE=nacos_devtest - MYSQL_USER=nacos - MYSQL_PASSWORD=nacos - LANG=C.UTF-8 volumes: - nacos-mysqldata:/var/lib/mysql ports: - "13306:3306" healthcheck: test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ] interval: 5s timeout: 10s retries: 10 prometheus: image: prom/prometheus:v2.52.0 container_name: prometheus restart: always ports: - 9090:9090 volumes: - prometheus-data:/prometheus - prometheus-conf:/etc/prometheus grafana: image: grafana/grafana:10.4.2 container_name: grafana restart: always ports: - 3000:3000 volumes: - grafana-data:/var/lib/grafana volumes: redis-data: redis-conf: mysql-conf: mysql-data: rabbit-data: rabbit-app: opensearch-data1: opensearch-data2: nacos-mysqldata: zookeeper_data: kafka-conf: kafka-data: kafkaui-app: prometheus-data: prometheus-conf: grafana-data: -
启动容器
docker compose up -d