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,则先卸载:
shyum 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工具
shyum install -y yum-utils \ device-mapper-persistent-data \ lvm2 --skip-broken
-
Step3: 配置Docker的yum源
shyum-config-manager --add-repo \ https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
shsed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo
shyum makecache fast
-
Step4: 安装Docker
shyum 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: 重启Docker
systemctl 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
-
执行以下两个命令刷新重载即可
shyum 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)
- d
ocekr 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容器
shdocker run -id --name=c3 -v /volume redis
注意:
挂载时并未指定宿主机的挂载目录(即此时宿主机为匿名数据卷),只指定了c3容器的目录,此时系统自动会去创建宿主机对应的挂载目录,如图所示
Name
:数据卷名称。由于定义容器未设置容器名,这里的就是匿名卷自动生成的名字,一串hash值。Source
:宿主机目录Destination
: 容器内的目录
上述配置是将容器内的
/volume
这个目录,与数据卷挂载。于是在宿主机中就有了/var/lib/docker/volumes/数据卷名称/_data
这个目录。这就是匿名数据卷对应的目录,其使用方式与普通数据卷没有差别。 -
Step2: 创建并启动名为c1的redis容器,然后通过
--volumns-from 数据卷容器名
来继承数据卷容器(即c3)shdocker run -id --name=c1 --volumns-from c3 redis
-
Step3: 创建并启动名为c2的redis容器,然后通过
--volumns-from 数据卷容器名
来继承数据卷容器(即c3)shdocker 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镜像并拉取镜像
shdocker search register.liberx.info/mysql docker pull mysql
-
Step2: 创建mysql目录并进入到该目录下
shmkdir ~/mysql cd ~/mysql
-
Step3: 创建并运行容器,同时设置端口映射、目录映射等
shdocker 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
:是设置时区;- M
YSQL_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容器内部
shdocker exec -it mysql /bin/bash
-
Step5: 登录mysql
- 输入命令
mysql -uroot -p
后输入密码即可登录
- 输入命令
-
步骤如图所示
-
之后就可以在外部机器中来连接该mysql容器并使用(此处以Navicat为例),步骤如图所示
-
Navicat创建连接
-
利用Navicat创建数据库(步骤略)
-
Tomcat部署
-
Step1: 查看Docker库是否有MySQL镜像并拉取镜像
shdocker search register.liberx.info/tomcat docker pull tomcat
-
Step2: 创建mysql目录并进入到该目录下
mkdir ~/tomcat cd ~/tomcat
-
Step3: 创建并运行容器,同时设置端口映射、目录映射等
shdocker 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镜像并拉取镜像
shdocker search register.liberx.info/nginx docker pull nginx
-
Step2: 创建nginx/conf目录并在该目录下创建nginx.conf文件
shmkdir ~/nginx cd ~/nginx mkdir conf cd conf vim nginx.conf
将以下命令复制到nginx.conf文件中
shuser 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目录下创建并运行容器,同时设置端口映射、目录映射等
shdocker 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镜像并拉取镜像
shdocker search register.liberx.info/redis docker pull redis
-
Step2: 创建mysql目录并进入到该目录下
mkdir ~/redis cd ~/redis
-
Step3: 创建并运行容器,同时设置端口映射、目录映射等
shdocker 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命令窗口输入以下命令进行测试
shredis-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
,该文件内容如下: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
:指定自定义镜像名及其版本号
- 由于博主已进入到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
,该文件内容如下: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 .
- 最后的
.
表示当前路径
- 最后的
- 由于博主已进入到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地址)-
也可使用
forma
t来过来结果直接得出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
shmv 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
,该文件代码如下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"
- 在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
服务)处理yamlserver { # 指定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网络已创建,具体过程可详见网络部分内容
shdocker 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拉取私有仓库
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.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" ] }
- 在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 私有镜像名:版本号
---版本号不可省略,如下所示
shdocker rmi 192.168.10.131:5000/centos:7
- 此时centos7私有镜像的id与centos7镜像的id一样,所以要想删除centos7私有镜像则必须为:
-
私有仓库拉取镜像
-
直接使用
docker pull 私有仓库服务器ip:5000/镜像名:镜像版本号