Docker完整技术汇总

Docker

背景引入

  • 在实际开发过程中有三个环境,分别是:开发环境、测试环境以及生产环境,假设开发环境中开发人员用的是jdk8,而在测试环境中测试人员用的时jdk7,这就导致程序员开发完系统后将其打成jar包发给测试人员后,测试人员由于环境不同而导致无法运行。

  • 此时如果开发人员将打好的jar包以及环境一起放到一个容器中,然后将容器发给测试人员,此时测试人员就不会因为环境不同而无法运行程序。这样也就规避了软件跨环境迁移问题

Docker架构

  • 如图所示,Docker主要分为三部分
    • Clients:客户端
      • Docker客户端用来向Docker发送命令
      • Docker客户端会随着Docker的安装而安装
    • Hosts:Docker核心
    • Registries:Docker远程仓库
  • 在Docker核心中有两部分:local host本机以及remote host远程机器
    • Docker在本机安装完之后,会以deamon守护进程的形式存在(即会在后台运行的进程)
    • 该守护进程中有两部分
      • image:镜像
      • container:容器
  • 镜像均来源于Docker远程仓库,该仓库主要有两种
    • 官方提供的仓库Docker Hub
    • 自己搭建的私有仓库Private registry

Docker基础定义

  • Docker:Docker是一种容器技术,解决软件跨环境迁移问题

    • 它可以帮助我们下载应用镜像,创建并运行镜像的容器。从而达到快速部署应用(即它可以让开发者打包他们的应用以及依赖包到一个轻量级的、可移植的容器中,然后发布到任意流行的Linux机器上)
  • 镜像:将应用所需的系统函数库、依赖、配置等与应用一起打包得到的就是镜像

    • Docker安装应用时会自动搜索并下载应用镜像(image)
    • 镜像仓库:存储和管理镜像的平台,Docker官方维护了一个公共仓库:Docker Hub
    • 注意:镜像可以让我们快速跨操作系统部署应用而忽略其运行环境、配置,是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖等
  • 容器:Docker会在运行镜像时创建一个相互隔离环境,称为容器

    • 容器使用的是沙箱机制,相互隔离,性能开销极低
  • 镜像与容器的关系

    • 它俩就像是面向对象程序设计中的类和对象一样,镜像是静态的定义,而容器是镜像运行时的实体
    • 容器可以被创建、启动、暂停、停止、删除等等

CentOS7安装Docker

  • Step1: 首先如果系统中已经存在旧的Docker,则先卸载:

    sh 复制代码
    yum remove docker \
        docker-client \
        docker-client-latest \
        docker-common \
        docker-latest \
        docker-latest-logrotate \
        docker-logrotate \
        docker-selinux \
        docker-engine-selinux \
        docker-engine \
        docker-ce
  • Step2: 安装yum工具

    sh 复制代码
    yum install -y yum-utils \
    	device-mapper-persistent-data \
    	lvm2 --skip-broken
  • Step3: 配置Docker的yum源

    sh 复制代码
    yum-config-manager --add-repo \
    	https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    sh 复制代码
    sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
    sh 复制代码
    yum makecache fast
  • Step4: 安装Docker

    sh 复制代码
    yum install -y docker-ce
  • Step5: Docker启动与校验

    sh 复制代码
    # 启动Docker
    systemctl start docker
    
    # 停止Docker
    systemctl stop docker
    
    # 重启
    systemctl restart docker
    
    # 设置开机自启
    systemctl enable docker
    
    # 执行docker ps命令,如果不报错,说明安装启动成功
    docker ps

Docker配置镜像加速(以阿里云为例)

  • Step1: 创建目录mkdir -p /etc/docker

  • Step2: 访问阿里官网在首页的产品中,找到阿里云的容器镜像服务

  • Step3: 配置镜像加速

    sh 复制代码
    # 注意把其中的镜像加速地址改成你自己的
    tee /etc/docker/daemon.json <<-'EOF'
    {
      "builder": {
        "gc": {
          "defaultKeepStorage": "20GB",
          "enabled": true
        }
      },
      "experimental": false,
      "registry-mirrors": [
      	"https://st5sw75p.mirrorcgrs572.aliyuncs.com",
        "https://docker.registry.cyou",
        "https://docker-cf.registry.cyou",
        "https://dockercf.jsdelivr.fyi",
        "https://docker.jsdelivr.fyi",
        "https://dockertest.jsdelivr.fyi",
        "https://mirror.aliyuncs.com",
        "https://dockerproxy.com",
        "https://mirror.baidubce.com",
        "https://docker.m.daocloud.io",
        "https://docker.nju.edu.cn",
        "https://docker.mirrors.sjtug.sjtu.edu.cn",
        "https://docker.mirrors.ustc.edu.cn",
        "https://mirror.iscas.ac.cn",
        "https://docker.rainbond.cc"
      ]
    }
    EOF
  • Step4: 重新加载配置systemctl daemon-reload

  • Step5: 重启Dockersystemctl restart docker

问题

  • 在使用yum安装时若包如图所示错误,则解决步骤如下

    • 通过vi /etc/yum.repos.d/CentOS-Base.repo打开文件CentOS-Base.repo,然后将文件中的镜像替换为阿里镜像,文件内容更改如下:

      sh 复制代码
      # CentOS-Base.repo
      #
      # The mirror system uses the connecting IP address of the client and the
      # update status of each mirror to pick mirrors that are updated to and
      # geographically close to the client.  You should use this for CentOS updates
      # unless you are manually picking other mirrors.
      #
      # If the mirrorlist= does not work for you, as a fall back you can try the 
      # remarked out baseurl= line instead.
      #
      #
       
      [base]
      name=CentOS-$releasever - Base - mirrors.aliyun.com
      failovermethod=priority
      baseurl=http://mirrors.aliyun.com/centos/$releasever/os/$basearch/
              http://mirrors.aliyuncs.com/centos/$releasever/os/$basearch/
              http://mirrors.cloud.aliyuncs.com/centos/$releasever/os/$basearch/
      gpgcheck=1
      gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
       
      #released updates 
      [updates]
      name=CentOS-$releasever - Updates - mirrors.aliyun.com
      failovermethod=priority
      baseurl=http://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
              http://mirrors.aliyuncs.com/centos/$releasever/updates/$basearch/
              http://mirrors.cloud.aliyuncs.com/centos/$releasever/updates/$basearch/
      gpgcheck=1
      gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
       
      #additional packages that may be useful
      [extras]
      name=CentOS-$releasever - Extras - mirrors.aliyun.com
      failovermethod=priority
      baseurl=http://mirrors.aliyun.com/centos/$releasever/extras/$basearch/
              http://mirrors.aliyuncs.com/centos/$releasever/extras/$basearch/
              http://mirrors.cloud.aliyuncs.com/centos/$releasever/extras/$basearch/
      gpgcheck=1
      gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
       
      #additional packages that extend functionality of existing packages
      [centosplus]
      name=CentOS-$releasever - Plus - mirrors.aliyun.com
      failovermethod=priority
      baseurl=http://mirrors.aliyun.com/centos/$releasever/centosplus/$basearch/
              http://mirrors.aliyuncs.com/centos/$releasever/centosplus/$basearch/
              http://mirrors.cloud.aliyuncs.com/centos/$releasever/centosplus/$basearch/
      gpgcheck=1
      enabled=0
      gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
       
      #contrib - packages by Centos Users
      [contrib]
      name=CentOS-$releasever - Contrib - mirrors.aliyun.com
      failovermethod=priority
      baseurl=http://mirrors.aliyun.com/centos/$releasever/contrib/$basearch/
              http://mirrors.aliyuncs.com/centos/$releasever/contrib/$basearch/
              http://mirrors.cloud.aliyuncs.com/centos/$releasever/contrib/$basearch/
      gpgcheck=1
      enabled=0
      gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
    • 执行以下两个命令刷新重载即可

      sh 复制代码
      yum clean all
      yum makecache

Docker命令

Docker服务相关命令

服务相关命令 解释
systemctl start docker 启动Docker服务
systemctl status docker 查看已经启动的Docker服务的状态
systemctl stop docker 停止Docker服务
systemctl restart docker 重启Docker服务
systemctl enable docker 设置Docker为开机自启动

Docker的Image镜像相关命令

注意:此处只列举常用镜像命令,其余可详见官方文档

命令 说明 文档地址
docker images 查看本地镜像 docker images
docker search + 镜像名 查看Docker库是否有对镜像
docker pull + 镜像名 拉取镜像 docker pull
docker push 推送镜像到DockerRegistry docker push
docker rmi 删除本地镜像 docker rmi
docker rmi f 强制删除本地镜像
docker build 构建镜像。详见自定义镜像部分内容
  • docker images -q:只显示所有镜像的id

  • docker search + 镜像名查看docker官方镜像时无法连接成功,但是可以直接docker pull + 镜像名来拉取镜像,原因:

    • 在现有版本中无法使用docker search + 镜像名查看docker官方镜像,而是使用docker search register.liberx.info/镜像名来查看docker官方镜像,如图所示

  • docker pull从docker仓库拉取镜像时,若不加版本号则会下载最新版本,若想加版本号则形式为:docker pull 镜像名:版本号。相应版本号可在Docker hub官网查看

  • 删除本地镜像时有两种方式:

    • 删除指定镜像
      • docker rmi + Image ID(即镜像ID)
      • docekr rmi + 镜像名:版本号
        • 一般不会加:版本号,除非系统中有多个版本的镜像
    • 删除所有镜像:docker rmi 'docker images -q'

代码示例

Docker容器相关命令

此处只列举出常用命令,具体可详见官网或菜鸟教程

命令 说明 文档地址
docker run 创建并运行容器 docker run
docker stop 停止指定容器 docker stop
docker start 启动指定容器(该容器已存在) docker start
docker restart 重新启动容器 docker restart
docker ps 查看正在运行的容器 docker ps
docker ps -a 查看创建的所有容器(包括运行和未运行的)
docker ps -aq 查看创建的所有容器的id(包括运行和未运行的)
docker rm +容器id或容器名 删除指定的未在运行的容器 docs.docker.com
docker rm -f +容器id或容器名 删除指定的正在运行的容器
docker rm 'docker ps -aq' 删除创建的所有未运行的容器
docker rm -f 'docker ps -aq' 删除创建的所有正在运行的容器
docker logs 查看容器运行日志 docker logs
docker exec -it 容器名 /bin/bash 进入容器 docker exec
docker exec -it 容器名 bash 进入容器
docker save 保存镜像到本地压缩文件 docker save
docker load -i 镜像压缩文件 加载本地压缩文件到镜像 docker load
docker inspect + 容器名 查看容器详细信息 docker inspect
docker update --restart=always [容器名/容器id] 设置指定Docker容器开机自启

docker run创建并运行容器

常用配置参数

配置参数 解释
-i 交互式操作容器
-t 给容器分配一个终端
-d 让容器后台运行
-p 宿主机端口:容器内端口 将宿主机(即Linux系统)端口映射到容器内的端口
-e 配置容器内的进程运行时的参数(即配置环境变量)
--name=自定义容器名--name 自定义容器名 给容器命名
--alias 自定义容器别名 给容器设置别名
-v 宿主机目录或文件:容器内目录或文件 配置数据卷,具体可详见数据卷配置内容
-- network 网络名 将容器加入到 已创建 的网络中。
REPOSITORY:TAG 镜像名:版本号,若未指定版本号则默认为最新版本
  • 若只用-it则在进入容器然后使用exit退出容器后,该容器也会自动停止运行

  • 若用-id则不能直接在docker run后加/bin/bash来直接进入容器,需使用docker exec -it 容器名 /bin/bashdocker exec -it 容器名 bash进入容器

    创建完后会自动显示当前容器的id,如图所示,即239d0287448eafe208a04a21a4b848c22a316bd39a5d7e5d02c12eb97d1e676f

  • -it-id的区别

    • -it创建的容器称为交互式容器,exit退出后就会结束运行
    • 交互式容器在创建时就可进入容器内
    • -id创建的容器为守护式容器,exit退出后仍然会在后台运行
    • 守护式容器必须通过docker exec -it 容器名 /bin/bashdocker exec -it 容器名 bash进入容器
  • 创建并运行容器时,默认进入的即是工作目录

  • -- network 网络名

    • 当使用docker run来创建并运行容器,同时将容器加入到对应的网络中时,若网络不存在,则必须使用网络相关命令先创建。具体创建过程可详见网络部分内容
    • 当在Docker Compose中将对应服务加入到网络中时,网络可以不存在,因为Docker Compose会自动创建对应的网路。详见Docker Compose部分内容

docker ps

不在示例,可详见docker run示例

  • docker ps:查看运行中容器,这个命令也可以加格式化访问,这样会更加清爽,如下所示
    • docker ps --format "table {``{.ID}}\t{``{.Image}}\t{``{.Ports}}\t{``{.Status}}\t{``{.Names}}"
  • docker ps -a:查看所有容器(包括运行中的和未运行的)。这个命令也可以加格式化访问,这样会更加清爽,如下所示
    • docker ps -a --format "table {``{.ID}}\t{``{.Image}}\t{``{.Ports}}\t{``{.Status}}\t{``{.Names}}"

设置命令别名

给常用Docker命令起别名,方便我们访问:

  • Step1: 通过vi /root/.bashrc修改/root/.bashrc文件 输入完该命令后即可进入到.bashrc文件,如图所示,原有文件内容如下:

    起完别名后wq保存并退出

Step2: 执行命令source /root/.bashrc使别名生效即可

数据卷

  • 数据卷是宿主机中的一个目录或文件,并且该目录或文件需要通过-v参数来与容器内的目录或文件进行映射

    • 当容器中的目录与数据卷目录绑定之后,此时任意一方的修改都会立即同步
    • 一个数据卷可以被多个容器同时挂载,可以此来实现容器间的数据交互
    • 一个容器也可以被挂载多个数据卷
  • 数据卷作用

    • 实现容器数据的持久化,此时数据不会随着容器的删除而消失
    • 实现外部机器与容器间的通信
    • 实现容器之间的数据交换
  • 注意

    • /var/lib/docker/volumes这个目录就是默认的存放所有容器数据卷的目录,其下会再根据数据卷名称创建新目录,格式为/数据卷名/_data
  • 为什么不让容器目录直接指向宿主机目录呢

    • 因为直接指向宿主机目录就与宿主机强耦合了,如果切换了环境,宿主机目录就可能发生改变了。由于容器一旦创建,目录挂载就无法修改,这样容器就无法正常工作了。
    • 但是容器指向数据卷,一个逻辑名称,而数据卷再指向宿主机目录,就不存在强耦合。如果宿主机目录发生改变,只要改变数据卷与宿主机目录之间的映射关系即可。

    不过,我们发现由于数据卷目录比较深,不好寻找,通常我们也允许让容器直接与宿主机目录挂载而不使用数据卷

数据卷相关命令

命令 说明 文档地址
docker volume create 创建数据卷 docker volume create
docker volume ls 查看所有数据卷 docs.docker.com
docker volume rm + 卷名 删除指定数据卷 docs.docker.com
docker volume inspect 查看某个数据卷的详情。若加卷名则查询指定数据卷;若不加则查看所有数据卷 docs.docker.com
docker volume prune 清除所有未使用的数据卷 docker volume prune

配置数据卷

容器与宿主机进行数据交换

  • 用到的命令
    • 创建并启动容器时,使用-v参数配置数据卷:docker run ... -v 宿主机目录或文件:容器内目录或文件...
    • 注意:
      • 目录或文件必须是绝对路径
      • 若目录或文件不存在,会自动创建
      • 可以挂载多个数据卷
      • 宿主机目录/root/...等同于~/...,而容器目录只能用/root/...

以redis为例

容器间数据交换

  • 有两种方式

    • 方式一:多个容器挂载同一个数据卷
    • 方式二:使用数据卷容器
    • 注意:方式一不在演示,主要演示方式二
  • 数据卷容器解释

    • 假设现在有三个容器:c1、c2、c3,c3挂载了一个数据卷,然后将c1、c2分别挂载到c3容器上,此时就相当于c1、c2、c3挂载了同一个数据卷。这样就实现了容器间的通信,此时就算c3容器出了问题,c1、c2仍然可以通过数据卷进行通信
    • c3就被称为数据卷容器
  • 示例

    • Step1: 创建并启动名为c3的redis容器

      sh 复制代码
      docker run -id --name=c3 -v /volume redis 

      注意:

      ​ 挂载时并未指定宿主机的挂载目录(即此时宿主机为匿名数据卷),只指定了c3容器的目录,此时系统自动会去创建宿主机对应的挂载目录,如图所示

      • Name:数据卷名称。由于定义容器未设置容器名,这里的就是匿名卷自动生成的名字,一串hash值。
      • Source:宿主机目录
      • Destination : 容器内的目录

      上述配置是将容器内的/volume这个目录,与数据卷挂载。于是在宿主机中就有了/var/lib/docker/volumes/数据卷名称/_data这个目录。这就是匿名数据卷对应的目录,其使用方式与普通数据卷没有差别。

    • Step2: 创建并启动名为c1的redis容器,然后通过--volumns-from 数据卷容器名来继承数据卷容器(即c3)

      sh 复制代码
      docker run -id --name=c1 --volumns-from c3 redis
    • Step3: 创建并启动名为c2的redis容器,然后通过--volumns-from 数据卷容器名来继承数据卷容器(即c3)

      sh 复制代码
      docker run -id --name=c2 --volumns-from c3 redis

挂载本地目录或文件

  • 容器间数据交换的示例Step1可知数据卷的目录比较深,如果我们去操作数据卷目录会不太方便。所以我们也会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:

    sh 复制代码
    # 挂载本地目录
    -v 本地目录:容器内目录
    # 挂载本地文件
    -v 本地文件:容器内文件

    注意

    本地目录或文件必须以 /./开头,如果直接以名字开头,则会被识别为数据卷名而非本地目录名。如下示例所示

    • -v mysql:/var/lib/mysql:会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
    • -v ./mysql:/var/lib/mysql:会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录

Docker应用部署

  • 从远程仓库拉取镜像的实现步骤

    • 搜索对应应用的镜像并拉取应用镜像

      注意:若本地有镜像压缩包,则直接将镜像压缩包上传到虚拟机中即可,此时就不需要该步骤了

    • 创建容器,并进行端口映射

    • 外部机器操作容器中的应用

  • 外部机器是无法直接操作容器,因为

    • 容器是隔离环境,外部容器与容器不互通;但是外部机器与宿主机是互通的,而宿主机又与容器互通,所以可以将宿主机的端口与容器端口进行一个映射,这样外部机器在访问宿主机对应端口时就相当于在访问容器。如图所示

MySQL部署

  • Step1: 查看Docker库是否有MySQL镜像并拉取镜像

    sh 复制代码
    docker search register.liberx.info/mysql
    docker pull mysql
  • Step2: 创建mysql目录并进入到该目录下

    sh 复制代码
    mkdir ~/mysql
    cd ~/mysql
  • Step3: 创建并运行容器,同时设置端口映射、目录映射等

    sh 复制代码
    docker run -id \
      --name mysql \
      -p 3307:3306 \
      -v $PWD/conf:/etc/mysql/conf.d \
      -v $PWD/logs:/logs \
      -v $PWD/data:/var/lin/mysql \
      -e TZ=Asia/Shanghai \
      -e MYSQL_ROOT_PASSWORD=123456 \
      mysql
    • --name 自定义容器名:自定义容器名
    • -p 宿主机端口:容器内端口:将宿主机的指定端口映射到容器内的指定端口
    • -e KEY=VALUE:配置容器内进程运行时的一些参数(即配置环境变量)。KEY和VALUE都由容器内进程决定
      • TZ=Asia/Shanghai:是设置时区;
      • MYSQL_ROOT_PASSWORD=123456:初始化root用户的mysql密码
    • -v 宿主机目录或文件:容器内目录或文件:配置数据卷
      • -v $PWD/conf:/etc/mysql/conf.d:配置目录挂载
      • -v $PWD/logs:/logs:日志目录挂载
      • -v $PWD/data:/var/lin/mysql:数据目录挂载
    • $PWD代表当前目录(即mysql目录下)
  • Step4: 进入mysql容器内部

    sh 复制代码
    docker exec -it mysql /bin/bash
  • Step5: 登录mysql

    • 输入命令mysql -uroot -p后输入密码即可登录
  • 步骤如图所示

  • 之后就可以在外部机器中来连接该mysql容器并使用(此处以Navicat为例),步骤如图所示

    • Navicat创建连接

    • 利用Navicat创建数据库(步骤略)

Tomcat部署

  • Step1: 查看Docker库是否有MySQL镜像并拉取镜像

    sh 复制代码
    docker search register.liberx.info/tomcat
    docker pull tomcat
  • Step2: 创建mysql目录并进入到该目录下

    mkdir ~/tomcat
    cd ~/tomcat
    
  • Step3: 创建并运行容器,同时设置端口映射、目录映射等

    sh 复制代码
    docker run -id \
      --name tomcat \
      -p 8080:8080 \
      -v $PWD:/usr/local/tomcat/webapps \
      tomcat
    • -v $PWD:/uer/local/tomcat/webapps:将容器当前目录挂载到容器的webapps中
  • Step4: 在Tomcat目录下创建一个test测试目录,并在该目录下创建文件index.html,文件代码如下

    html 复制代码
    <h1>Tomcat访问成功</h1>
  • Step5: 外部机器测试是否成功

Nginx部署

  • Step1: 查看Docker库是否有MySQL镜像并拉取镜像

    sh 复制代码
    docker search register.liberx.info/nginx
    docker pull nginx
  • Step2: 创建nginx/conf目录并在该目录下创建nginx.conf文件

    sh 复制代码
    mkdir ~/nginx
    cd ~/nginx
    mkdir conf
    cd conf
    vim nginx.conf

    将以下命令复制到nginx.conf文件中

    sh 复制代码
    user  nginx;
    worker_processes  1;
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
        keepalive_timeout  65;
        #gzip  on
        include /etc/nginx/conf.d/*.conf
    }
  • Step3: 返回到nginx目录下创建并运行容器,同时设置端口映射、目录映射等

    sh 复制代码
    docker run -id \
      --name=nginx \
      -p 80:80 \
      -v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
      -v $PWD/logs:/var/log/nginx \
      -v $PWD/html:/usr/share/nginx/html \
      nginx
    • -v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf:配置文件挂载
    • -v $PWD/logs:/var/log/nginx:日志目录挂载
    • -v $PWD/html:/usr/share/nginx/html:静态资源目录挂载
  • Step4: 外部机器测试是否成功

  • 配置文件内容解析

    sh 复制代码
    # 指定运行nginx 的用户,默认是 nginx 用户
    user  nginx;
    # 定义工作进程数,若为auto则表示自动根据 CPU 核心数调整
    worker_processes  1;
    # 定义错误日志文件的位置和日志级别; warn 表示记录警告及更高级别的错误信息
    error_log  /var/log/nginx/error.log warn;
    # 定义 Nginx 启动后保存进程 ID 的文件路径,用于管理进程
    pid        /var/run/nginx.pid;
    
    # 事件块
    events {
    	# 每个工作进程允许的最大并发连接数
        worker_connections  1024;
    }
    # HTTP块 定义 Web 服务相关配置
    http {
      # 引入外部文件 /etc/nginx/mime.types,定义各种文件的 MIME 类型
        include       /etc/nginx/mime.types;
        # 设置默认 MIME 类型。当无法识别文件类型时,使用 application/octet-stream,即通用的二进制流
        default_type  application/octet-stream;
    	# 定义日志格式
    	# $remote_addr:客户端 IP 地址
    	# $remote_user:客户端认证的用户名
    	# $time_local:本地时间
    	# $request:客户端请求的完整内容
    	# $status:HTTP 状态码
    	# $body_bytes_sent:发送给客户端的响应体字节数
    	# $http_referer:请求来源(Referer)
    	# $http_user_agent:用户代理信息(如浏览器类型)
    	# $http_x_forwarded_for:代理服务器传递的客户端真实 IP(如果存在)
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    	# 指定访问日志的存储位置和日志格式(使用上面定义的 main)
        access_log  /var/log/nginx/access.log  main;
    	#  开启高效文件传输
        sendfile        on;
        # 提高文件传输性能
        #tcp_nopush     on;
        # 定义 HTTP 长连接的超时时间(秒)。客户端连接超过该时间未发送请求时将断开。
        keepalive_timeout  65;
        # 开启HTTP响应的 Gzip 压缩以减少传输数据量
        #gzip  on
        # 引入 /etc/nginx/conf.d/ 目录下的所有配置文件,支持多个虚拟主机
        include /etc/nginx/conf.d/*.conf
    }

Redis部署

  • Step1: 查看Docker库是否有MySQL镜像并拉取镜像

    sh 复制代码
    docker search register.liberx.info/redis
    docker pull redis
  • Step2: 创建mysql目录并进入到该目录下

    mkdir ~/redis
    cd ~/redis
    
  • Step3: 创建并运行容器,同时设置端口映射、目录映射等

    sh 复制代码
    docker run -id \
      --name redis \
      -p 6380:6379 \
      redis
    • 若报如下错误则代表宿主机的6379端口号被占用,此时换个宿主机端口号即可

      Error starting userland proxy: listen tcp4 0.0.0.0:6379: bind: address already in use.

  • Step4: 使用外部机器redis测试是否成功

    注意:要进入到windows的redis目录下打开cmd命令窗口输入以下命令进行测试

    sh 复制代码
    redis-cli.exe -h 宿主机ip地址 -p nginx容器端口号

Docker自定义镜像

  • 自定义镜像主要分为四步:

    • 准备Linux运行环境(java项目并不需要完整的操作系统,仅仅是基础运行环境即可)
    • 安装并配置JDK
    • 拷贝jar包
    • 配置启动脚本

    上述步骤中的每一次操作其实都是在生产一些文件(系统运行环境、函数库、配置最终都是磁盘文件),所以镜像就是一堆文件的集合

    但需要注意的是,镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一id,称为Layer)。这样,如果我们构建时用到的某些层其他人已经制作过,就可以直接拷贝使用这些层,而不用重复制作。

    例如,第一步中需要的Linux运行环境,通用性就很强,所以Docker官方就制作了这样的只包含Linux运行环境的镜像。我们在制作java镜像时,就无需重复制作,直接使用Docker官方提供的CentOS或Ubuntu镜像作为基础镜像 。然后再搭建其它层即可,这样逐层搭建,最终整个Java项目的镜像结构如图所示:

  • Docker镜像原理

  • 用到的方法

    命令 说明 文档地址
    docker save 保存镜像到本地压缩文件 docker save
    docker load -i 镜像压缩文件 加载本地压缩文件到镜像 docker load
    docker inspect + 容器名 查看容器详细信息 docker inspect

利用命名方式制作

  • 通过指定容器创建自定义镜像:docker commit 容器id 自定义镜像名称:自定义版本号
  • 将自定义的镜像转为压缩文件:docker save -o 自定义压缩文件名称 自定义镜像名称:自定义版本号
  • 将自定义镜像转为的压缩文件转为另一个镜像:docker load -i 压缩文件名称

注意:容器转为自定义的镜像后,目录挂载(即数据卷)中的内容不会添加到新的镜像中,若想要其中的内容,则可以在利用自定义的对象创建容器时配置数据卷就可以了

利用Dockerfile制作(自定义镜像)

由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。这种记录镜像结构的文件就称为Dockerfile ,其对应的语法可以参考官方文档

  • Dockerfile是一个记录镜像结构的文本文件,包含了一条条指令,每一条指令构建一层基于基础的镜像,最终构建出一个新的镜像
    • 对于开发人员:可以为开发团队提供一个完全一致的开发环境
    • 对于测试人员:可以直接拿开发时所创建的镜像或者通过Dockerfile文件来创建一个新的镜像开始工作
    • 对于运维人员:在部署时,可以实现应用的无缝移植

快速入门

需求:定义Dockerfile,发布SpringBoot项目到Docker容器中

本快速入门项目DockerFileDemo的具体搭建可完全参考SpringBoot快速入门

  • Step1: 执行Maven构建指令package来对该SpringBoot项目打包

  • Step2: 将该SpringBoot项目的jar包传到宿主机的root目录下

  • Step3: 利用mkdir /root/docker-files(等同于mkdir ~/docker-files)命令在root目录下创建项目文件目录docker-files,来存放项目文件(如 JAR 包、Dockerfile 等)

    • 若命令为mkdir ./docker-filesmkdir docker-files则必须保证当前所在目录为root目录,因为.表示在当前目录下创建
  • Step4: 将该jar包移动到docker-files目录下:mv DockerFileDemo-0.0.1-SNAPSHOT.jar ./docker-files/

  • Step5: 利用vim ./docker-files/dockerFileDemodocker-files目录下创建并编写该项目对应的dockerfile文件dockerFileDemo,该文件内容如下:

    sh 复制代码
    # 指定基础镜像(即父镜像)
    FROM openjdk:21-jdk
    # 指明维护者/作者信息
    LABEL maintainer="cgrs572 <Your.Name@example.com>"
    # 将对应jar包复制到即将要创建的镜像的app目录中
    COPY DockerFileDemo-0.0.1-SNAPSHOT.jar /app/DockerFiledemo.jar
    # 指定容器创建时的默认命令
    CMD ["java", "-jar", "/app/DockerFiledemo.jar"]
    • 指定的父镜像若在系统中不存在的话,后续构建自定义镜像时该父镜像也会被下载。只是说此时构建自定义镜像的时间可能会延长,可提前自行利用docker pull 镜像名:版本号来将父镜像下载到宿主机中
  • Step6: 利用cd /root/docker-files进入docker-files目录

  • Step7: 利用docker build -f dockerfile文件路径 -t 自定义镜像名:版本号 对应的dockerfile文件所在目录来构建镜像

    • 由于博主已进入到docker-files目录,所以最终命令为:docker build -f ./dockerFileDemo -t dockerfiledemcon .
      • 最后的.表示当前路径
    • 命令解析
      • -f:指定dockerfile文件及其路径
      • -t:指定自定义镜像名及其版本号
  • Step8: 创建并运行容器docker run -id -p 9000:8080 dockerfiledemcon

  • Step9: 外部机器测试是否运行成功

利用Dockerfile制作(自定义官方镜像)

背景引入

本案例以CentOS7为例

  • Step1: 从远程镜像仓库拉取Centos7到本地:docker pull centos:7

    • 若本地有centos7镜像则该步省略
  • Step2: 创建并运行centos容器并进入该容器中docker run -it --name=c1 centos /bin/bash

    • 此处的命令可省略/bin/bash,因为在官方的centos的dockerfile文件中的CMD命令已经指定了容器创建时的默认命令为 /bin/bash
  • Step3: cd到root目录下,然后执行vim a.txt命令,最终截图如下

  • 在以上示例中就存在问题

    • 进入容器后默认进入的工作目录为/
    • 官方提供的centos镜像没有下载vim命令导致该命令不可用
    • 因此为了更加方便,我们就可以来自定义镜像

快速入门

  • Step1: 利用mkdir /root/docker-files(等同于mkdir ~/docker-files)命令在root目录下创建项目文件目录docker-files,来存放项目文件(如 JAR 包、Dockerfile 等)

    • 若命令为mkdir ./docker-filesmkdir docker-files则必须保证当前所在目录为root目录,因为.表示在当前目录下创建

    注意:由于在子当以镜像的示例中已创建该目录,所以该示例截图中不存在该步骤的命令

  • Step2: 利用vim ./docker-files/centosdockerFiledocker-files目录下创建并编写该项目对应的dockerfile文件centosdockerFile,该文件内容如下:

    sh 复制代码
    # 指定基础镜像(即父镜像)
    FROM centos:7
    # 指明维护者/作者信息
    LABEL maintainer="cgrs572 <Your.Name@example.com>"
    # 指定在构建自定义镜像过程中执行的命令(即 利用RUN安装vim到自定义镜像中)
    RUN yum install -y vim
    # 设置后续指令的工作目录(即利用`WORKDIR`指定默认工作目录)
    WORKDIR /usr
    # 指定容器创建时的默认命令
    CMD ["/bin/bash"]
    • 指定的父镜像若在系统中不存在的话,后续构建自定义镜像时该父镜像也会被下载。只是说此时构建自定义镜像的时间可能会延长,可提前自行利用docker pull 镜像名:版本号来将父镜像下载到宿主机中

    • 注意:若在构建自定义镜像源过程中yum无法下载则需要更换centos镜像的镜像源,此时dockerfile文件代码如下

      sh 复制代码
      # 指定基础镜像(即父镜像)
      FROM centos:7
      # 指明维护者/作者信息
      LABEL maintainer="cgrs572 <Your.Name@example.com>"
      # 更换yum 镜像源保证yum可以正常工作
      RUN curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo && yum install -y vim
      # 指定在构建自定义镜像过程中执行的命令(即 利用RUN安装vim到自定义镜像中)
      RUN yum install -y vim
      # 设置后续指令的工作目录(即利用`WORKDIR`指定默认工作目录)
      WORKDIR /usr
      # 指定容器创建时的默认命令
      CMD ["/bin/bash"]
  • Step3: 利用cd /root/docker-files进入docker-files目录

  • Step4: 利用docker build -f dockerfile文件路径 -t 自定义镜像名:版本号 对应的dockerfile文件所在目录来构建镜像

    • 由于博主已进入到docker-files目录,所以最终命令为:docker build -f ./centosdockerFile -t centosdockerfile .
      • 最后的.表示当前路径
  • Step5: 创建并运行容器docker run -id -p 9000:8080 centosdockerfile ,然后测试是否运行成功

    • 此时进容器后默认的工作目录为/usr
    • 使用vim测试并未报错

DockerFile常用关键字

Dockerfile 指令 解释
FROM 指定基础镜像(即父镜像),用于后续的指令构建。即指定Dockerfile是基于哪个image构建的
MAINTAINER 指明Dockerfile的作者/维护者。(已弃用,推荐使用LABEL指令)
LABEL 添加镜像的元数据,使用键值对的形式。
RUN 指定在构建自定义镜像过程中执行的命令。
CMD 指定容器创建时的默认命令。(可以被docker run时指定的命令覆盖)
ENTRYPOINT 设置容器创建时的主要命令。(不可被docker run时指定的命令覆盖)
EXPOSE 声明容器运行时监听的特定网络端口。
ENV 在容器内部设置环境变量。
ADD 将文件、目录或远程URL添加到镜像中。
COPY 将文件或目录复制到镜像中。
VOLUME 为容器创建挂载点或声明卷。
WORKDIR 设置后续指令的工作目录。
USER 指定后续指令的用户上下文。
ARG 定义在构建过程中传递给构建器的变量,可使用 "docker build" 命令设置。
ONBUILD 当该镜像被用作另一个构建过程的基础时,添加触发器。
STOPSIGNAL 设置发送给容器以退出的系统调用信号。
HEALTHCHECK 定义周期性检查容器健康状态的命令。
SHELL 覆盖Docker中默认的shell,用于RUN、CMD和ENTRYPOINT指令。

网络

背景引入

容器间互相访问方式步骤如下:

以MySQL镜像与自定义centos镜像为例

  • Step1:创建并运行项目MySQL镜像对应的容器以及自定义centos7镜像对应的容器(步骤略)

    • 创建完成后使用docker ps -a指令查看容器是否创建成功

      • MySQL镜像对应的容器名为mysql
      • 自定义centos7镜像对应的容器名为centos01
  • Step2:使用docker inspect 容器名指令来查看容器mysql的Networks.bridge.IPAddress属性(即ip地址)

    • 也可使用format来过来结果直接得出ip地址:docker inspect --format='{``{range .NetworkSettings.Networks}}{``{println .IPAddress}}{``{end}}' 容器名

    • 容器mysql的ip地址为172.17.0.2,如图所示

  • Step3:进入容器centos01中,利用ping 172.17.0.2检测是否能够访问容器mysql

    注意:若该容器未启动则需要先利用docker start 容器名/id将其启动,然后利用docker exec -it 容器id/容器名 /bin/bash进入

    有图可知,只要知道对应容器的ip地址就可以实现容器间的互相访问

快速入门

由背景引入可知只要知道对应容器的ip地址就可以实现容器间的互相访问

但是,容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时MySQL容器的IP发生变化,这就会导致连接会失败,所以通过ip地址来访问还是不可靠,所以就有了网络,步骤如下

  • Step1: 利用docker network create 自定义网络名创建一个网络,博主创建的网络名为webb

  • Step2: 利用docker network ls查看所有网络,判断是否对应网络是否创建成功

  • Step3: 利用docker network connect 容器要加入的网络名 要加入的容器 --alias 自定义容器别名来将mysql容器和centos01容器均加入创建的网络webb中

  • Step4: 进入容器centos01中,利用ping 容器名或容器对应的别名检测是否能够访问容器mysql

网络相关命令

命令 说明 文档地址
docker network create 创建一个网络 docker network create
docker network ls 查看所有网络 docs.docker.com
docker network rm 删除指定网络 docs.docker.com
docker network prune 清除未使用的网络 docs.docker.com
docker network connect 使指定容器连接加入某网络 docs.docker.com
docker network disconnect 使指定容器连接离开某网络 docker network disconnect
docker network inspect 查看网络详细信息 docker network inspect

Docker Compose

我们部署一个简单的java项目,至少包含3个容器:

  • MySQL
  • Nginx
  • Java项目

而稍微复杂的项目,其中还会有各种各样的其它中间件,需要部署的东西远不止3个。如果还像之前那样手动的逐一部署,就太麻烦了。

而Docker Compose就可以帮助我们实现多个相互关联的Docker容器的快速部署。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器。

  • Docker Compose是一个编排多容器分布式部署的工具,提供命令集来管理容器化应用的完整开发周期,包括服务构建、启动和停止
  • 使用步骤
    • 利用Dockerfile定义运行环境镜像
    • 使用docker-compose.yml定义组成应用的各个服务
    • 运行docker-compose up启动应用

Docker Compose安装

二进制包离线安装(推荐)

  • Step1:去Github下载对应版本的二进制文件

  • Step2:利用cd /usr/local/bin进入到/usr/local/bin目录下,然后将二进制文件直接上传到该目录下

  • Step3:利用mv oldName newName将文件docker-compose-linux-x86_64重命名为 docker-compose

    sh 复制代码
    mv docker-compose-linux-x86_64 docker-compose
  • Step4:添加可执行权限sudo chmod +x /usr/local/bin/docker-compose

  • Step5:验证是否安装成功docker-compose --version

  • 卸载时,直接删除对应的二进制包即可

快速入门

需求:使用DockerCompose编排nginx+springboot项目

本示例以Docker自定义镜像的springboot项目为基准。在Docker自定义镜像中,已经构建了自定义了springboot项目对象的镜像,如图所示

  • Step1: 将对应的官方镜像从docker仓库拉取下来:docker pull 镜像名:版本号

  • Step2: 自定义项目的镜像(本步骤略,可详见自定镜像的部分内容示例)

  • Step3: 利用mkdir /root/docker-compose(等同于mkdir ~/docker-files)命令在root目录下创建项目文件目录docker-compose,来存放项目文件(如 JAR 包、Dockerfile 等)

    • 若命令为mkdir ./docker-composemkdir docker-compose则必须保证当前所在目录为root目录,因为.表示在当前目录下创建
  • Step4: 利用cd docker-compose进入到docker-compose目录下,然后利用vim docker-compose.yml创建dockercompose文件docker-compose.yml,该文件代码如下

    yaml 复制代码
    # 指定dockercompose文件格式的版本
    version: '3.8'
    # 定义服务
    services:
      # 定义服务1:nagix服务---自定义服务名即可
      nginx:
        # image: 镜像名:版本号
        image: nginx
        # 主机端口:容器端口 将主机端口映射到容器对应端口
        ports:
          - 80:80
        # 将指定服务链接到本服务中,后期在该服务创建的容器中可直接通过指定服务名来访问指定服务
        links:
          - app
        # 将本地目录或文件挂载到容器内的目录或文件
        volumes:
          - ./nginx/conf.d:/etc/nginx/conf.d
      # 定义服务2:app服务---自定义服务名即可
      app:
        # image: 镜像名:版本号
        image: dockerfiledemcon
        # 指定该服务对应的容器内部暴露的端口
        expose:
          - "8080"
    • 在dockercompose新版本中version已被舍弃,不过最好还是加上
    • 在dockercompose新版本中links已被舍弃,先版本可以通过服务名称直接访问其他服务,而不需要显式地使用 links,所以可删除

    最终文件代码如下:

    yaml 复制代码
    # 指定dockercompose文件格式的版本
    version: '3.8'
    # 定义服务
    services:
      # 定义服务1:nagix服务---自定义服务名即可
      nginx:
        # image: 镜像名:版本号
        image: nginx
        # 主机端口:容器端口 将主机端口映射到容器对应端口
        ports:
          - 80:80
        # 将本地目录或文件挂载到容器内的目录或文件
        volumes:
          - ./nginx/conf.d:/etc/nginx/conf.d
      # 定义服务2:app服务---自定义服务名即可
      app:
        # image: 镜像名:版本号
        image: dockerfiledemcon
        # 自定义该服务创建的容器名称
        container_name: appcon
        # 在同一网络下暴露该服务对应的容器端口
        expose:
          - "8080"
  • Step5: 创建挂载的本地目录或文件 mkdir -p ./nginx/conf.d

    • -p用来创建目录及其子目录
  • Step6: 利用cd ./nginx/conf.d进入到conf.d目录下并在该目录下用vim nginx.conf创建并编写nginx配置文件nginx.conf文件,该文件代码如下

    解释:当服务器监听到 80 端口的请求时,nginx 会自动将请求转发到 app 服务的 8080 端口

    此时nginx 会充当一个反向代理服务器,将客户端的请求转发给后端服务(app 服务)处理

    yaml 复制代码
    server {
        # 指定nginx服务器监听的端口
        listen 80;
        # 关闭访问日志记录
        access_log off;
        # 定义一个位置块,处理所有以/开头的请求
        location / {
            # 将请求代理到名为app服务的8080端口
            proxy_pass http://app:8080;
        }
    }
  • Step7: 在~/docker-compose目录下使用docker-compose up命令启动容器

    • 该命令若为docker-compose up -d则代表后台启动
  • Step8: 测试访问,运行成功

注意

  • 在使用Docker Compose来实现多个相互关联的Docker容器的快速部署时, 若不定义并指定网络,则Docker Compose会自动创建一个默认网络,以此来实现不同服务对应的容器均在同一个默认网络下,并能够通过服务名互相访问

    • 在以上快速入门中就属于未定义并指定网络,此时Docker Compose会创建一个默认的网络,如图所示

    • 在Docker Compose基本语法中的两个示例属于定义并指定网络

  • expose:在同一网络下暴露该服务对应的容器端口

    • 此时如果我在外部利用docker run -id -p 9000:8080 dockerfiledemcon命令创建了一个app服务所使用的镜像的容器,并将宿主机的9000端口映射到容器的8000端口上,则:
      • docker run -p 9000:8080 这条命令是将 宿主机的 9000 端口 映射到 容器的 8080 端口。这意味着外部世界(例如,浏览器或者其他客户端)通过宿主机的 9000 端口可以访问到容器的 8080 端口
      • expose 是告诉 Docker 仅在容器网络中暴露端口 ,并不进行宿主机与容器之间的端口映射。expose 只是让其他同网络中的容器可以访问到暴露的端口。它并不会将容器的端口映射到宿主机的端口
      • 所以它们是互不干扰,互不影响的。但是假设产生了影响则在app服务中利用container_name指明该服务所创建的容器名称即可

Docker Compose基本语法

  • docker run参数对应的docker compose指令

    docker run 参数 docker compose 指令 说明
    --name container_name 指定容器名称
    -p ports 端口映射
    -e environment 环境变量
    -v volumes 数据卷配置
    --network networks 网络
  • 其它docker compose指令

    docker compose 指令 说明
    build 指定该服务的镜像是通过 Dockerfile 文件进行构建的
    context 指定 Dockerfile文件及利用该文件构建镜像所需的其他文件所在的位置
    dockerfile 指定要构建的镜像所对应的dockerfile文件名称。如果未指定,则会默认查找名为 Dockerfile 的文件
    image 指定服务要使用的镜像名称及版本号(版本号可省略)
    depends_on 指定服务之间的启动顺序,指定的服务会在当前服务启动之前启动
    expose 在同一网络下暴露该服务对应的容器端口
  • build

    • 若要使用的自定义镜像不存在且无法从官方仓库拉取,则指定该服务的镜像是通过 Dockerfile 文件进行构建的。此时Docker Compose会自动根据Dockerfile文件来创建自定义镜像

示例1

此处以网络中的示例为例,将MySQL镜像容器加入到自定义的网络webb中

  • 创建并运行MySQ镜像的容器代码如下:

    • 当使用docker run时,容器要加入的网络必须是已存在的;若不存在则需要提前创建好对应的网络。
    • 此处假设自定义的webb网络已创建,具体过程可详见网络部分内容
    sh 复制代码
    docker run -id \
      --name mysql \
      -p 3307:3306 \
      -v $PWD/conf:/etc/mysql/conf.d \
      -v $PWD/logs:/logs \
      -v $PWD/data:/var/lin/mysql \
      -e TZ=Asia/Shanghai \
      -e MYSQL_ROOT_PASSWORD=123456 \
      --network webb
      mysql
  • 如果用docker-compose.yml文件来定义,就是这样:

    • 此处假设webb网络在外部不存在,则文件代码如下:

      docker run命令不同的是:在Docker Compose文件中的网络可以不存在,因为Docker Compose会自动创建对应的网路(前提是该网络并未指定在外部存在)。

      yaml 复制代码
      # 指定dockercompose文件格式的版本
      version: "3.8"
      # 定义服务
      services:
        # 定义服务1:nagix服务---自定义服务名即可
        mysql:
          # image: 镜像名:版本号
          image: mysql
          # 自定义该服务创建的容器名称
          container_name: mysql
          # 主机端口:容器端口 将主机端口映射到容器对应端口
          ports:
            - "3306:3306"
          # 配置容器内的进程运行时的参数(即配置环境变量)
          environment:
            # 设置时区
            TZ: Asia/Shanghai
            # 设置root用户的登录密码
            MYSQL_ROOT_PASSWORD: 123
          # 将本地目录或文件挂载到容器内的目录或文件
          volumes:
            - "./mysql/conf:/etc/mysql/conf.d"
            - "./mysql/data:/var/lib/mysql"
          # 该服务创建的容器加入到指定的网络中
          networks:
            # 要加入的网络的别名
            - newwebb
      # 定义网络
      networks:
        # 定义网络别名
        newwebb:
          # 定义网络名称
          name: webb
    • 此处假设webb网络在外部存在,则文件代码如下:

      注意:若假设在外部存在的webb网络其实在外部是不存在的,此时Docker Compose就不会自动创建对应网络,需手动创建(具体过程可详见网络部分内容)

      • 网络别名与外部网络的实际名称不一致

        yaml 复制代码
        # 指定dockercompose文件格式的版本
        version: "3.8"
        # 定义服务
        services:
          # 定义服务1:nagix服务---自定义服务名即可
          mysql:
            # image: 镜像名:版本号
            image: mysql
            # 自定义该服务创建的容器名称
            container_name: mysql
            # 主机端口:容器端口 将主机端口映射到容器对应端口
            ports:
              - "3306:3306"
            # 配置容器内的进程运行时的参数(即配置环境变量)
            environment:
              # 设置时区
              TZ: Asia/Shanghai
              # 设置root用户的登录密码
              MYSQL_ROOT_PASSWORD: 123
            # 将本地目录或文件挂载到容器内的目录或文件
            volumes:
              - "./mysql/conf:/etc/mysql/conf.d"
              - "./mysql/data:/var/lib/mysql"
            # 该服务创建的容器加入到指定的网络中
            networks:
              # 要加入的网络的别名
              - newwebb
        # 定义网络
        networks:
          # 定义网络别名
          newwebb:
            # 指定外部已存在的网络
            external:
              # 已存在的网络名称
              name: webb
      • 网络别名与外部网络的实际名称一致

        yaml 复制代码
        # 指定dockercompose文件格式的版本
        version: "3.8"
        # 定义服务
        services:
          # 定义服务1:nagix服务---自定义服务名即可
          mysql:
            # image: 镜像名:版本号
            image: mysql
            # 自定义该服务创建的容器名称
            container_name: mysql
            # 主机端口:容器端口 将主机端口映射到容器对应端口
            ports:
              - "3306:3306"
            # 配置容器内的进程运行时的参数(即配置环境变量)
            environment:
              # 设置时区
              TZ: Asia/Shanghai
              # 设置root用户的登录密码
              MYSQL_ROOT_PASSWORD: 123
            # 将本地目录或文件挂载到容器内的目录或文件
            volumes:
              - "./mysql/conf:/etc/mysql/conf.d"
              - "./mysql/data:/var/lib/mysql"
            # 该服务创建的容器加入到指定的网络中
            networks:
              # 要加入的网络的别名
              - newwebb
        # 定义网络
        networks:
          # 定义网络别名
          webb:
            # 指定该网络在外部已存在
            external: true

示例2

黑马商城部署文件

yaml 复制代码
# 指定dockercompose文件格式的版本
version: "3.8"
# 定义服务
services:
  # 定义服务1:mysql服务---自定义服务名即可
  mysql:
    # image: 镜像名:版本号
    image: mysql
    # 自定义该服务创建的容器名称
    container_name: mysql
    # 主机端口:容器端口 将主机端口映射到容器对应端口
    ports:
      - "3306:3306"
    # 配置容器内的进程运行时的参数(即配置环境变量)
    environment:
      # 设置时区
      TZ: Asia/Shanghai
      # 设置root用户的登录密码
      MYSQL_ROOT_PASSWORD: 123
    # 将本地目录或文件挂载到容器内的目录或文件
    volumes:
      - "./mysql/conf:/etc/mysql/conf.d"
      - "./mysql/data:/var/lib/mysql"
      - "./mysql/init:/docker-entrypoint-initdb.d"
    # 该服务创建的容器加入到指定的网络中
    networks:
      # 要加入的网络的别名
      - hm-net
      
  # 定义服务2:hmall服务---自定义服务名即可
  hmall:
   # 指定该服务的镜像是通过 Dockerfile 文件进行构建的
    build: 
      # 指定构建镜像所需的所有文件所在位置
      context: .
      # 指定Dockerfile文件名称,若未指定则默认为Dockerfile
      dockerfile: Dockerfile
    # 自定义该服务创建的容器名称
    container_name: hmall
    # 主机端口:容器端口 将主机端口映射到容器对应端口
    ports:
      - "8080:8080"
    # 该服务创建的容器加入到指定的网络中
    networks:
      - hm-net
    # 指定服务之间的启动顺序,指定的mysql服务会在当前hmall服务启动之前启动
    depends_on:
      - mysql
  # 定义服务3:nginx服务---自定义服务名即可
  nginx:
    # image: 镜像名:版本号
    image: nginx
    # 自定义该服务创建的容器名称
    container_name: nginx
    # 主机端口:容器端口 将主机端口映射到容器对应端口
    ports:
      - "18080:18080"
      - "18081:18081"
    # 将本地目录或文件挂载到容器内的目录或文件
    volumes:
      - "./nginx/nginx.conf:/etc/nginx/nginx.conf"
      - "./nginx/html:/usr/share/nginx/html"
    # 指定服务之间的启动顺序,指定的mysql服务会在当前hmall服务启动之前启动
    depends_on:
      - hmall
    # 该服务创建的容器加入到指定的网络中
    networks:
      - hm-net
      
# 定义网络
networks:
  # 定义网络别名
  hm-net:
    # 定义网络名称
    name: hmall

Docker Compose基本命令

  • docker compose [OPTIONS] [COMMAND]

    类型 参数或指令 说明
    Options -f 指定compose文件的路径和名称
    Options -p 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念
    Commands up 创建并启动所有service容器
    Commands down 停止并移除所有容器、网络
    Commands ps 列出所有启动的容器
    Commands logs 查看指定容器的日志
    Commands stop 停止容器
    Commands start 启动容器
    Commands restart 重启容器
    Commands top 查看运行的进程
    Commands exec 在指定的运行中容器中执行命令

Docker私有仓库

Docker官方的Docker hub是一个用于管理公共镜像的仓库,我们可以从上面拉取镜像到本地,也可以把自己的镜像推送上去。但是有时候我们的服务器无法访问互联网,或者不希望将自己的镜像放到公网当中,这就需要搭建自己的私有仓库来存储和管理自己的镜像了

搭建私有仓库

  • Step1: 从Docker Hub拉取私有仓库registrydocker pull registry

  • Step2: 创建并启动私有仓库容器:docker run -id --name=registry -p 5000:5000 registry

  • Step3: 浏览器输入私有仓库的ip地址:映射的端口号/v2/_catalog测试是否成功

    • {"repositories":[]}表示私有仓库,由于现在并未向私有仓库推送镜像,所以为空
  • Step4: 修改/ect/docker目录下的daemon.json文件:vim /etc/docker/daemon.json

    etc目录与root目录同级,所以直接/etc即可

    • 在deamon.json文件中添加私有仓库服务器的ip以及端口号:{"insecure-registries":["私有仓库服务器ip:端口号"]}---以此来让Docker信任该私有仓库
    json 复制代码
    {
      "builder": {
        "gc": {
          "defaultKeepStorage": "20GB",
          "enabled": true
        }
      },
      "experimental": false,
      "registry-mirrors": [
        "https://st5sw75p.mirrorcgrs572.aliyuncs.com",
        "https://docker.registry.cyou",
        "https://docker-cf.registry.cyou",
        "https://dockercf.jsdelivr.fyi",
        "https://docker.jsdelivr.fyi",
        "https://dockertest.jsdelivr.fyi",
        "https://mirror.aliyuncs.com",
        "https://dockerproxy.com",
        "https://mirror.baidubce.com",
        "https://docker.m.daocloud.io",
        "https://docker.nju.edu.cn",
        "https://docker.mirrors.sjtug.sjtu.edu.cn",
        "https://docker.mirrors.ustc.edu.cn",
        "https://mirror.iscas.ac.cn",
        "https://docker.rainbond.cc"
      ],
      "insecure-registries": [
       "192.168.10.131:5000"
      ]
    }
  • Step5: 重启Docker服务:systemctl restart docker

  • Step6: 启动私有仓库容器:docker start registry

上传镜像到私有仓库

以CentOS7镜像为例

  • Step1: 将镜像标记为私有仓库的镜像:docker tag 镜像名:镜像版本号 私有仓库服务器ip:5000/镜像名:镜像版本号

  • Step2: 上传标记的镜像到私有仓库:docker push 私有仓库服务器ip:5000/镜像名:镜像版本号

  • Step3: 浏览器输入私有仓库的ip地址:映射的端口号/v2/_catalog测试是否成功

  • 注意:

    • 为方便后续私有仓库拉取镜像,所以此处会将本地centos7私有镜像删除

      • 此时centos7私有镜像的id与centos7镜像的id一样,所以要想删除centos7私有镜像则必须为:docker rmi 私有镜像名:版本号---版本号不可省略,如下所示
      sh 复制代码
      docker rmi 192.168.10.131:5000/centos:7

私有仓库拉取镜像

  • 直接使用docker pull 私有仓库服务器ip:5000/镜像名:镜像版本号

相关推荐
小钟不想敲代码31 分钟前
Docker部署Sentinel
docker·容器·sentinel
Tester_孙大壮1 小时前
了解智能运维
运维
胖毁青春,瘦解百病2 小时前
Docker镜像源设置不生效问题排查
docker·容器
fnd_LN2 小时前
Linux文件目录 --- mkdir命令,创建目录,多级目录,设置目录权限
linux·运维·服务器
会飞的土拨鼠呀2 小时前
Flannel是什么,如何安装Flannel
运维·云原生·kubernetes
木与子不厌2 小时前
微服务自定义过滤器
运维·数据库·微服务
行思理3 小时前
Linux 下SVN新手操作手册
linux·运维·svn
嘤嘤怪呆呆狗3 小时前
【开发问题记录】使用 Docker+Jenkins+Jenkins + gitee 实现自动化部署前端项目 CI/CD(centos7为例)
前端·vue.js·ci/cd·docker·gitee·自动化·jenkins
沛沛老爹3 小时前
CI/CD是什么?
运维·git·ci/cd
IPdodo全球网络服务4 小时前
如何通过TikTok引流到私域流量池
运维·服务器·网络