Docker
背景引入
-  在实际开发过程中有三个环境,分别是:开发环境、测试环境以及生产环境,假设开发环境中开发人员用的是jdk8,而在测试环境中测试人员用的时jdk7,这就导致程序员开发完系统后将其打成jar包发给测试人员后,测试人员由于环境不同而导致无法运行。  
-  此时如果开发人员将打好的jar包以及环境一起放到一个容器中,然后将容器发给测试人员,此时测试人员就不会因为环境不同而无法运行程序。这样也就规避了软件跨环境迁移问题  
Docker架构

- 如图所示,Docker主要分为三部分 
  - Clients:客户端 
    - Docker客户端用来向Docker发送命令
- Docker客户端会随着Docker的安装而安装
 
- Hosts:Docker核心
- Registries:Docker远程仓库
 
- Clients:客户端 
    
- 在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,则先卸载: 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工具 yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 --skip-broken
-  Step3: 配置Docker的yum源 yum-config-manager --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.reposed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repoyum makecache fast
-  Step4: 安装Docker yum install -y docker-ce
-  Step5: Docker启动与校验 # 启动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: 配置镜像加速   # 注意把其中的镜像加速地址改成你自己的 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: 重启Docker systemctl restart docker
问题

-  在使用yum安装时若包如图所示错误,则解决步骤如下 -  通过 vi /etc/yum.repos.d/CentOS-Base.repo打开文件CentOS-Base.repo,然后将文件中的镜像替换为阿里镜像,文件内容更改如下:# 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
-  执行以下两个命令刷新重载即可 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/bash或docker exec -it 容器名 bash进入容器创建完后会自动显示当前容器的id,如图所示,即 239d0287448eafe208a04a21a4b848c22a316bd39a5d7e5d02c12eb97d1e676f 
-  -it与-id的区别- -it创建的容器称为交互式容器,- exit退出后就会结束运行
- 交互式容器在创建时就可进入容器内
- -id创建的容器为守护式容器,- exit退出后仍然会在后台运行
- 守护式容器必须通过docker exec -it 容器名 /bin/bash或docker 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/...
 
 
- 创建并启动容器时,使用-v参数配置数据卷:
以redis为例

容器间数据交换
-  有两种方式 - 方式一:多个容器挂载同一个数据卷
- 方式二:使用数据卷容器
- 注意:方式一不在演示,主要演示方式二
 
-  数据卷容器解释  - 假设现在有三个容器:c1、c2、c3,c3挂载了一个数据卷,然后将c1、c2分别挂载到c3容器上,此时就相当于c1、c2、c3挂载了同一个数据卷。这样就实现了容器间的通信,此时就算c3容器出了问题,c1、c2仍然可以通过数据卷进行通信
- c3就被称为数据卷容器
 
-  示例 -  Step1: 创建并启动名为c3的redis容器 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)docker run -id --name=c1 --volumns-from c3 redis
-  Step3: 创建并启动名为c2的redis容器,然后通过 --volumns-from 数据卷容器名来继承数据卷容器(即c3)docker run -id --name=c2 --volumns-from c3 redis
 
-  
挂载本地目录或文件
-  由 容器间数据交换的示例Step1可知数据卷的目录比较深,如果我们去操作数据卷目录会不太方便。所以我们也会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:# 挂载本地目录 -v 本地目录:容器内目录 # 挂载本地文件 -v 本地文件:容器内文件注意: 本地目录或文件必须以 /或./开头,如果直接以名字开头,则会被识别为数据卷名而非本地目录名。如下示例所示- -v mysql:/var/lib/mysql:会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
- -v ./mysql:/var/lib/mysql:会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
 
Docker应用部署
-  从远程仓库拉取镜像的实现步骤 -  搜索对应应用的镜像并拉取应用镜像 注意:若本地有镜像压缩包,则直接将镜像压缩包上传到虚拟机中即可,此时就不需要该步骤了 
-  创建容器,并进行端口映射 
-  外部机器操作容器中的应用 
 
-  
-  外部机器是无法直接操作容器,因为 - 容器是隔离环境,外部容器与容器不互通;但是外部机器与宿主机是互通的,而宿主机又与容器互通,所以可以将宿主机的端口与容器端口进行一个映射,这样外部机器在访问宿主机对应端口时就相当于在访问容器。如图所示
  
MySQL部署

-  Step1: 查看Docker库是否有MySQL镜像并拉取镜像 docker search register.liberx.info/mysql docker pull mysql
-  Step2: 创建mysql目录并进入到该目录下 mkdir ~/mysql cd ~/mysql
-  Step3: 创建并运行容器,同时设置端口映射、目录映射等 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容器内部 docker exec -it mysql /bin/bash
-  Step5: 登录mysql - 输入命令mysql -uroot -p后输入密码即可登录
 
- 输入命令
-  步骤如图所示  
-  之后就可以在外部机器中来连接该mysql容器并使用(此处以Navicat为例),步骤如图所示 -  Navicat创建连接  
-  利用Navicat创建数据库(步骤略) 
 
-  
Tomcat部署
-  Step1: 查看Docker库是否有MySQL镜像并拉取镜像 docker search register.liberx.info/tomcat docker pull tomcat
-  Step2: 创建mysql目录并进入到该目录下 mkdir ~/tomcat cd ~/tomcat
-  Step3: 创建并运行容器,同时设置端口映射、目录映射等 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,文件代码如下 <h1>Tomcat访问成功</h1>
-  Step5: 外部机器测试是否成功  
Nginx部署
-  Step1: 查看Docker库是否有MySQL镜像并拉取镜像 docker search register.liberx.info/nginx docker pull nginx
-  Step2: 创建nginx/conf目录并在该目录下创建nginx.conf文件 mkdir ~/nginx cd ~/nginx mkdir conf cd conf vim nginx.conf将以下命令复制到nginx.conf文件中 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目录下创建并运行容器,同时设置端口映射、目录映射等 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: 外部机器测试是否成功  
-  配置文件内容解析 # 指定运行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镜像并拉取镜像 docker search register.liberx.info/redis docker pull redis
-  Step2: 创建mysql目录并进入到该目录下 mkdir ~/redis cd ~/redis
-  Step3: 创建并运行容器,同时设置端口映射、目录映射等 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命令窗口输入以下命令进行测试 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-files或mkdir docker-files则必须保证当前所在目录为root目录,因为.表示在当前目录下创建
 
- 若命令为
-  Step4: 将该jar包移动到 docker-files目录下:mv DockerFileDemo-0.0.1-SNAPSHOT.jar ./docker-files/
-  Step5: 利用 vim ./docker-files/dockerFileDemo在docker-files目录下创建并编写该项目对应的dockerfile文件dockerFileDemo,该文件内容如下:# 指定基础镜像(即父镜像) 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:指定自定义镜像名及其版本号
 
 
- 由于博主已进入到docker-files目录,所以最终命令为:
-  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-files或mkdir docker-files则必须保证当前所在目录为root目录,因为.表示在当前目录下创建
 注意:由于在子当以镜像的示例中已创建该目录,所以该示例截图中不存在该步骤的命令 
- 若命令为
-  Step2: 利用 vim ./docker-files/centosdockerFile在docker-files目录下创建并编写该项目对应的dockerfile文件centosdockerFile,该文件内容如下:# 指定基础镜像(即父镜像) 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文件代码如下 # 指定基础镜像(即父镜像) 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 .- 最后的.表示当前路径
 
- 最后的
  
- 由于博主已进入到docker-files目录,所以最终命令为:
-  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-composemv 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-compose或mkdir docker-compose则必须保证当前所在目录为root目录,因为.表示在当前目录下创建
 
- 若命令为
-  Step4: 利用 cd docker-compose进入到docker-compose目录下,然后利用vim docker-compose.yml创建dockercompose文件docker-compose.yml,该文件代码如下# 指定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,所以可删除
 最终文件代码如下: # 指定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"
- 在dockercompose新版本中
-  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服务)处理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 指令 说明 --namecontainer_name指定容器名称 -pports端口映射 -eenvironment环境变量 -vvolumes数据卷配置 --networknetworks网络 
-  其它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网络已创建,具体过程可详见网络部分内容
 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会自动创建对应的网路(前提是该网络并未指定在外部存在)。# 指定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就不会自动创建对应网络,需手动创建(具体过程可详见网络部分内容) -  网络别名与外部网络的实际名称不一致 # 指定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
-  网络别名与外部网络的实际名称一致 # 指定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
黑马商城部署文件
# 指定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拉取私有仓库 registry:docker 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.jsonetc目录与root目录同级,所以直接 /etc即可- 在deamon.json文件中添加私有仓库服务器的ip以及端口号:{"insecure-registries":["私有仓库服务器ip:端口号"]}—以此来让Docker信任该私有仓库
 { "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" ] }
- 在deamon.json文件中添加私有仓库服务器的ip以及端口号:
-  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 私有镜像名:版本号—版本号不可省略,如下所示
 docker rmi 192.168.10.131:5000/centos:7
- 此时centos7私有镜像的id与centos7镜像的id一样,所以要想删除centos7私有镜像则必须为:
 
-  
私有仓库拉取镜像
-  直接使用 docker pull 私有仓库服务器ip:5000/镜像名:镜像版本号 



















