Docker

109 阅读4分钟

Linux安装

centos7.x安装

  • 卸载原始docker
$ sudo yum remove docker \
        docker-client \
        docker-client-latest \
        docker-common \
        docker-latest \
        docker-latest-logrotate \
        docker-logrotate \
        docker-engine
  • 安装docker依赖
$ sudo yum install -y yum-utils \
  device-mapper-persistent-data \
  lvm2
  • 设置docker的yum源
$ sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
  • 安装最新版的docker
$ sudo yum install docker-ce docker-ce-cli containerd.io
  • 指定版本安装docker
    • $ sudo yum install docker-ce-<VERSION_STRING> docker-ce-cli-<VERSION_STRING> containerd.io
$ yum list docker-ce --showduplicates | sort -r
$ sudo yum install docker-ce-18.09.5-3.el7 docker-ce-cli-18.09.5-3.el7 containerd.io
  • docker命令
# 开机启动&启动docker
systemctl enable docker
systemctl start docker
# 关闭docker
systemctl stop docker

所有平台安装

  • 通过国内源安装docker应用
curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh --mirror Aliyun
  • 启动docker
systemctl enable docker
systemctl start docker
  • 创建docker用户,并设置docker组
groupadd docker
groupadd -g docker docker

配置阿里云加速

登录阿里云官网,工作台-镜像容器服务-镜像工具-镜像加速器

image.png

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://9b2k04q7.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

核心架构

image.png

  • 镜像:一个镜像代表一个应用环境,是一个只读文件,比如mysql镜像,redis镜像,tomcat镜像等等;
  • 容器:镜像每次运行之后就会产生一个容器,就是正在运行的镜像,可读可写;
  • 仓库:用来存放镜像的位置,类似与maven的远程仓库;
  • dockerFile:docker生成镜像的配置文件,用来书写自定义镜像的一些配置;
  • tar:对镜像打包的文件,可以恢复成为镜像

容器

数据卷

数据卷实现了容器与宿主机数据共享问题(只能在镜像第一次启动时指定数据卷)

docker run [-d][-p][--name][-v] 容器名/容器id
-d 后台守护进程运行
-p 指定宿主机与容器的端口映射
--name 指定容器名称
-v 指定数据卷

docker run -d -p 8080:8080 --name tomcat8 -v /opt/apps:/usr/local/tomcat/webapps tomcat:8.0
-v /opt/apps:/usr/local/tomcat/webapps
/opt/apps:宿主机地址
/usr/local/tomcat/webapps:容器路径(绑定数据卷后会以/opt/apps的文件夹内容为主,可能会将当前目录下文件清空)

# 保留容器数据卷内容,通过别名形式,默认数据卷地址为   /usr/lib/docker/volum/别名/_data
-v 别名:/usr/local/tomcat/webapps

# 容器内对数据卷只读,只能有宿主机操作  ro:Ready Only
-v 别名:/usr/local/tomcat/webapps:ro

高级数据卷

  1. 自定义提前创建好宿主机数据卷,在容器启动时进行别名绑定
  2. 在容器启动时使用未创建的别名绑定,那么会由Docker为我们创建一个为别名的宿主机数据卷,地址在:/usr/lib/docker/volum/别名/_data
docker volume list 							# 查看数据卷
docker volume create 数据卷名 		                # 创建数据卷
docker volume inspect 数据卷名 	                # 数据卷信息
docker volume rm 数据卷名 				     # 删除数据卷

数据卷详情

[root@iZbp18eahm3m5nczl60fo4Z ~]# docker volume inspect aaa
[
    {
        "CreatedAt": "2022-09-03T14:54:23+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/aaa/_data",
        "Name": "aaa",
        "Options": null,
        "Scope": "local"
    }
]

镜像

# 容器打包成为镜像
docker commit -m "描述" -a "作者" 容器id  打包后镜像名:TAG(版本)
# 打包镜像
docker save 镜像名 -o 名称.tar
# 恢复载入镜像
docker reload -i 名称.tar

软件安装

mysql 8.0.30

# 从DockerHub仓库中拉去mysql8.0.30版本镜像文件
docker pull mysql:8.0.30

# 启动命令
docker run -d -p 3306:3306 --name mysql --restart=always  -e MYSQL_ROOT_PASSWORD=nieao0823.. -v /usr/local/docker/mysql/conf.d:/etc/mysql/conf.d -v /usr/local/docker/mysql/data:/var/lib/mysql mysql:8.0.30
-e MYSQL_ROOT_PASSWORD=nieao0823.. 									# 指定root密码
--restart=always																		# docker重启后自动加载该容器
-v /usr/local/docker/mysql/conf.d:/etc/mysql/conf.d # mysql配置文件与宿主机绑定
-v /usr/local/docker/mysql/data:/var/lib/mysql 			# mysql的数据与宿主机进行绑定
-d 后台运行 -p 端口映射 --name设置名称

# 导出全部库结构+数据
docker exec 容器名/容器id sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql
# 导出指定库结构+数据
docker exec mysql sh -c 'exec mysqldump --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql 
# 导出指定库表结构(不包含数据)
docker exec mysql sh -c 'exec mysqldump --no-data --databases 库表 -uroot -p"$MYSQL_ROOT_PASSWORD"' > /root/all-databases.sql  
# 执行sql
docker exec -i mysql sh -c 'exec mysql -uroot -p"$MYSQL_ROOT_PASSWORD"' < /root/xxx.sql

解决 Authentication plugin ‘caching_sha2_password‘ cannot be loaded 问题

# 原因是Nactive密码加密方式与mysql版本不一致导致,要么升级Nactive,要么将mysql的加密方式回退,此处采用重新指定mysql加密方式来进行
docker exec -it mysql bash # 进入mysql容器
mysql -u root -p # 进入mysql
# 修改账户密码加密规则
ALTER USER 'root'@'%' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER;
# 更新用户的密码
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
# 刷新权限
FLUSH PRIVILEGES;
# 重置密码
alter user 'root'@'%' identified by 'nieao0823..';

redis 6.2.7

docker run -d -p 6379:6379 --name redis --restart=always -v /usr/local/docker/redis/conf:/usr/local/etc/redis -v /usr/local/docker/redis/data:/data redis:6.2.7 redis-server /usr/local/etc/redis/redis.conf 

--restart=always 	# docker 重启后自动加载该容器
-v /usr/local/docker/redis/conf:/usr/local/etc/redis # 数据卷、配置文件宿主机与容器同步
-v /usr/local/docker/redis/data:/data 	# 数据卷、Redis开启AOF日志持久化后,容器redis数据与宿主机同步
redis-server /usr/local/etc/redis/redis.conf  # redis启动时加载指定路径的配置文件

高级

网络通讯

高级网络配置

当Docker启动时,会自动在宿主机上创建一个docker0的虚拟网桥,实际上是Linux的一个birdge,可以理解为一个软件交换机,他会在挂载到它的网口进行转发。当创建一个Docker容器时,同时会创建一对veth pair接口(当数据包发送到一个接口时,另外一个接口时也是可以收到相同的数据包,这就是为什么通过-p命令可以实现宿主机与容器之间的端口通信)。容器端即eth0,则另一个是本地挂载在docker0网桥,名称以veth0开头,通过这种方式,主机可以跟容器之间通信,容器之间也可以通信。

使用自定义网络桥段后,在容器内部依然可以互通,而且还可以通过容器名称来当做ip使用。

image.png

网络桥段命令

[root@iZbp18eahm3m5nczl60fo4Z ~] docker network list # 查看网络桥段信息,默认bridge桥接模式
NETWORK ID     NAME      DRIVER    SCOPE
76c7e4783347   bridge    bridge    local
b6cd3b9ff50b   host      host      local
a2180011fe38   none      null      local

docker network create -d bridge 网桥名称 	# 创建网桥
docker network rm 网桥名称 	       # 删除网桥
docker network list             # 查看全部网桥
docker network connect 网桥名称 容器id/名称  # 容器加入指定网桥
docker inspect 容器id/名称 	          # 可以查看容器网络信息

使用自定义网络桥段

容器启动时指定网络桥段

docker run -d -p 8080:8080 --name tomcat01 --network 网桥名称 tomcat:8.0
--network # 指定网络桥段名称

容器启动后加入某网络桥段

docker network connect 网络桥段名称 容器id/名称

Dockerfile

Dokcerfile是Docker镜像的描述文件、是由一系列命令和参数构成的脚本,主要用来构建docker镜像的构建文件。

关键字作用
FROM当前镜像是基于那个镜像的、第一个必须是FROM
RUN构建镜像时候需要运行的命令
EXPOSE当前容器对暴露的端口号
WORKDIR进入容器内落位置
ENV用来构建镜像过程中的环境变量($ENV_NAME)
ADD将宿主机上的文件拷贝至镜像(ADD命令会自动处理url和解压tar包)
COPY类似与ADD、宿主机内构建文件所在的目录下的文件拷贝至镜像内目标路径
VOLUME容器数据卷,用于数据保存和持久化工作
CMD指定一个容器启动时要运行的命令、Dockerfile可以有多个cm指定,但是只会有最后一个生效、cmd会被docker run之后的参数替换
ENTRYPOINT指定一个容器启动时运行的命令,ENTRYPOINT和CMD一样,都是在容器启动参数

构建SpringBoot项目镜像

编写Dockerfile文件

FROM openjdk:8
WORKDIR /ems
ADD ems.jar /ems
EXPOSE 80
ENTRYPOINT ["java","-jar"]
CMD ["ems.jar"]

# FROM 基于jdk8镜像开始构建
# WORKDIR 进入容器落脚点/ems
# ADD 将当前构建文件所在目录下的ems.jar拷贝到容器内的ems目录下
# EXPOSE 向外暴露端口 80
# ENTRYPOINT 【CMD】命令 java -jar ems.jar
# 此处项目名称使用CMD、是因为CMD是不固定、可以在Docker run 命令之后对其进行更改、java-jar是固定的命令,项目名称可能不是固定


docker build -t ems:version .
    images_name 镜像名
    version 指定版本,可以忽略不写,不指定版本则为最新版本 latest
    Dockerfile文件与项目的jar包要处于统一目录
    docker images 可以查看生成的容器信息
    最后的.不要忘记


docker run -d -p 80:80 --name ems --restart=always ems:9,1 ems.jar

Docker Compose

Docker compose 实现对容器的编排

  • 项目(project)是由一组容器(服务)构成的一个完整业务单元,在docker-compose.yml文件中定义
  • 服务(service)一个应用容器,实际上可以运行多个相同镜像的实例

安装

Linux

curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

# 国内源
curl -L https://download.fastgit.org/docker/compose/releases/download/1.27.4/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

chmod +x /usr/local/bin/docker-compose

安装包

下载地址

# 安装
mv docker-compose-Linux-x86_64 docker-compose # 重命名
mv docker-compose /usr/local/bin 	# 移动至bin

[root@iZbp18eahm3m5nczl60fo4Z bin]# docker-compose --version
docker-compose version 1.25.5, build 8a1c60f6


# 卸载
rm -rf /usr/local/bin/docker-compose

docker-compose 模板文件

默认模板文件名称为:docker-compose.yml,类型为yml version:"3.8" 第一行显示docker-compse版本、具体版本与docker版本相关(docker --version) 版本查看

  • services 下面开始配置项目所需要的应用容器(第一个是容器的id,针对于这个项目的服务容器id)
  • container_name 容器名(docker ps 中显示的容器)
  • image 基于什么镜像
  • ports 端口映射
  • volumes 与宿主机的数据卷
  • command容器启动后指定执行的命令
  • restart: always 应用重启后自启
  • depends_on 配置容器服务加载顺序
  • build自定义构建镜像来(不能与image共存)
    • context 指定Dockerfile文件所在的上下文
    • dockerfile Dockefile文件名
    • arg Dockerfile文件中参数

demo

version: "3.8"
# 项目服务
services:
  nginx: # 服务名
    container_name: "my_nginx"
    image: nginx # 基于那个镜像
    ports: # 开放端口
      - "80:80"
    volumes: # 数据卷
      - "/usr/local/docker/nginx/index.html:/usr/share/nginx/html/index.html"
    # command: echo "docker-compose services nginx install" # 容器启动后指定命令
    restart: always # 应用重启后自启
    depends_on: # 在以下容器启动后再启动当前容器
      - tomcat
  tomcat:
    container_name: "my_tomcat"
    image: "tomcat:${TOMCAT_VERSION}"
    ports:
      - "8080:8080"
    volumes:
      - "/usr/local/docker/tomcat/index.jsp:/usr/local/tomcat/webapps/ROOT/index.jsp"
    # command: echo "docker-compose services tomcat install"
    restart: always
  ems:
    container_name: "my_ems"
    build:
      context: ./docker-file # 指定Dockerfile所在文件夹的路径
      dockerfile: ems-Dockerfile # 指定Dcokerfile文件名
      args:
        PROJECT_NAME: ems.jar
    ports:
      - "8099:8099"
    restart: always
    depends_on: # 在以下容器启动后再启动当前容器
      - tomcat
      - nginx
.env文件

docker-compose编排模板中有一些密码或者常量信息可以通过外部的.env文件来进行管理,因为当前文件是.开头隐藏文件,所以一般是看不到,使用ll -a命令可以看到,格式 key = value、在docker-compose.yml中可以通过 ${TOMCAT_VERSION} 来引入。

[root@iZbp18eahm3m5nczl60fo4Z compose]# cat .env
TOMCAT_VERSION=9.0
基本命令
docker-compose up -d [service]   后台启动容器编排文件

docker-compose down    此命令后停止up命令所启动的容器,并移除网络

docker-compose exec [service]    入指定容器

docker-compose ps [service]    列出项目中所有的容器

docker-compose restart [service]   重启项目中容器

docker-compose rm -f [service]    删除项目中所有容器

docker-compose start [service]   启动项目中容器(或指定容器)

docker-compose stop [service]   暂停项目中容器(或指定容器)
mysql+redis+nginx+nacos+rabbitmq 编排文件
version: "3.8"

services:
  mysql:
    container_name: "app_mysql"
    image: "mysql:8.0.30"
    # 重启策略
    restart: always
    networks:
      - app
    # 端口映射
    ports:
      - "3306:3306"
    volumes:
      # 数据挂载
      - "/usr/local/docker/app/mysql/data:/var/lib/mysql"
      # 配置文件挂载
      - "/usr/local/docker/app/mysql/config:/etc/mysql/conf.d"
    environment:
      # root用户密码
      MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}
      # mysql时区
      TZ: Asia/Shanghai
    command:
      # 将mysql8.0默认密码策略修改为原先策略 (mysql8.0对其默认策略做了更改 会导致密码无法匹配)
      --default-authentication-plugin=mysql_native_password
      --character-set-server=utf8mb4
      --collation-server=utf8mb4_general_ci
      --explicit_defaults_for_timestamp=true
      --lower_case_table_names=1
  redis:
    container_name: "app_redis"
    image: "redis:6.2.7"
    restart: always
    networks:
      - app
    ports:
      - "6379:6379"
    volumes:
      # 数据挂载、配置文件挂载、日志信息挂载
      - "/usr/local/docker/app/redis/data:/data"
      - "/usr/local/docker/app/redis/config/redis.conf:/usr/local/redis/config/redis.conf"
      - "/usr/local/docker/app/redis/logs:/logs"
    # 启动命令
    command: ["redis-server","/usr/local/redis/config/redis.conf"]
  nginx:
    container_name: "app_nginx"
    # 基于那个镜像
    image: "nginx"
    networks:
      - app
    # 开放端口
    ports:
      - "80:80"
    volumes:
      - "/usr/local/docker/app/nginx/config/nginx.conf:/etc/nginx/nginx.conf"
      - "/usr/local/docker/app/nginx/logs:/var/log/nginx"
    restart: always # 应用重启后自启
  nacos:
    container_name: "app_nacos"
    image: "nacos/nacos-server:2.0.2"
    networks:
      - app
    restart: always
    ports:
      - "8848:8848"
    environment:
      # 单机启动
      MODE: standalone
  rabbitmq:
    container_name: "app_rabbitmq"
    image: "rabbitmq:3.7.15"
    networks:
      - app
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER}
      RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS}
      RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_DEFAULT_VHOST}
    volumes:
      - "/usr/local/docker/app/rabbitmq/data:/usr/lib/rabbitmq"

networks:
  app: