一篇文章掌握Docker
一.Docker概述
1.什么是Docker
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是一种容器技术,解决软件跨环境迁移的问题。
2.Docker主要功能
打包:就是把你软件运行所需的依赖、第三方库、软件打包到一起,变成一个安装包
分发:你可以把你打包好的“安装包”上传到一个镜像仓库,其他人可以非常方便的获取和安装
部署:拿着“安装包”就可以一个命令运行起来你的应用,自动模拟出一模一样的运行环境,不管是 在 Windows/Mac/Linux。
二.Docker架构
Docker使用客户端-服务器架构。 Docker客户端(client) 与 守护进程(Docker daemon)进行对话,该守护进程完成了构建、运行和分发 Docker 容器的繁重工作。
仓库(Repository):是docker提供的一个用来保存镜像的仓库。
镜像(Image):镜像就是一个可执行的包,用来创建容器,docker中每一个软件就是一个镜像。
容器(Container):容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
三.Docker安装
1.卸载旧版
为了防止如果系统中已经存在旧的Docker,则先卸载:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine \
docker-selinux
2.配置Docker的yum库
首先安装一个yum工具:
通过加上 sudo
,你告诉系统以超级用户权限来执行该命令,允许你进行系统级的更改。如果你没有使用 sudo
,普通用户通常没有权限来执行某些操作,系统会拒绝执行。如果已经是以 root 用户身份登录,你就不需要加 sudo
。
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
安装成功后,执行命令,配置Docker的yum源:
sudo yum-config-manager \
--add-repo \
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
更新yum,建立缓存:
sudo yum makecache fast
3.安装Docker
最后,执行命令,安装Docker:
yum install -y docker-ce docker-ce-cli containerd.io \
docker-buildx-plugin docker-compose-plugin
4.启动校验
# 启动Docker
systemctl start docker
# 停止Docker
systemctl stop docker
# 重启
systemctl restart docker
# 设置开机自启
systemctl enable docker
# 执行docker ps命令,如果不报错,说明安装启动成功
docker ps
5.配置镜像加速
配置镜像步骤如下:
# 创建目录
mkdir -p /etc/docker# 复制内容
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"http://hub-mirror.c.163.com",
"https://mirrors.tuna.tsinghua.edu.cn",
"http://mirrors.sohu.com",
"https://ustc-edu-cn.mirror.aliyuncs.com",
"https://ccr.ccs.tencentyun.com",
"https://docker.m.daocloud.io",
"https://docker.awsl9527.cn"
]
}
EOF# 重新加载配置
systemctl daemon-reload# 重启Docker
systemctl restart docker
镜像地址可能会变更,如果失效可以找最新的docker镜像。
四.快速入门
1.部署MySQL
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=root \
mysql
当我们利用Docker安装应用时,Docker会自动搜索并下载应用镜像(image)。镜像不仅包含应用本身,还包含应用运行所需要的环境、配置、系统函数库。Docker会在运行镜像时创建一个隔离环境,称为容器(container)。
镜像仓库:存储和管理镜像的平台,Docker官方维护了一个公共仓库:hub.docker.com
2.命令解读
-
docker run -d
:创建并运行一个容器,-d
则是让容器以后台进程运行 -
--name mysql
:容器起个名字叫mysql
,名字必须是唯一的 -
-p 3306:3306
:设置端口映射-
容器是隔离环境,外界不可访问。但是可以将宿主机端口映射容器内端口,当访问宿主机指定端口时, 就是在访问容器内的端口了。
-
容器内端口往往是由容器内的进程决定,例如 MySQL 进程默认端口是3306,因此容器内端口一定是3306。而宿主机端口则可以任意指定,一般与容器内保持一致。
-
格式:-p 宿主机端口:容器内端口,示例中就是将宿主机的3306映射到容器内的3306端口
-
-
-e TZ=Asia/Shanghai
:容器内进程运行时的环境变量-
格式:-e KEY=VALUE,KEY和VALUE都由容器内进程决定
-
-
mysql
:设置镜像名称,Docker会根据这个名字搜索并下载镜像-
格式:REPOSITORY:TAG,例如:mysql:8.0,其中 REPOSITORY 可以理解为镜像名,TAG 是版本号。在未指定TAG的情况下,默认是最新版本,也就是
mysql:latest
。
-
五.Docker基础
1.常见命令
1.命令解读
docker pull #拉取镜像
docker push #推送镜像到DockerRegistry
systemctl enable docker #Docker开机自启
docker images #查看本地镜像
docker rmi #删除本地镜像
docker run #创建并运行容器 (不能重复创建)
docker stop #停止指定容器
docker start #启动指定容器
docker restart #重新启动容器
docker update --restart=always [容器名/容器id] #Docker容器开机自启
docker rm #删除指定容器
docker ps #查看容器
docker logs #查看容器运行日志
docker exec #进入容器
docker save #保存镜像到本地压缩文件
docker load #加载本地压缩文件到镜像
docker inspect #查看容器详细信息
命令之间的关系:
在不知道命令用法的时候,可以在命令后面加上 --help查看相关用法,例如:
docker save --help
2. 演示——Nginx
# 第1步,去DockerHub查看nginx镜像仓库及相关信息
# 第2步,拉取Nginx镜像
docker pull nginx# 第3步,查看镜像
docker images
# 结果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB# 第4步,创建并允许Nginx容器
docker run -d --name nginx -p 80:80 nginx# 第5步,查看运行中容器
docker ps
# 也可以加格式化方式访问,格式会更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"# 第6步,访问网页,地址:http://虚拟机地址
# 第7步,停止容器
docker stop nginx# 第8步,查看所有容器
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"# 第9步,再次启动nginx容器
docker start nginx# 第10步,再次查看容器
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"# 第11步,查看容器详细信息
docker inspect nginx# 第12步,进入容器,查看容器内目录
docker exec -it nginx bash
# 或者,可以进入MySQL
docker exec -it mysql mysql -uroot -p# 第13步,删除容器
docker rm nginx
# 若发现无法删除,因为容器运行中,可加上 -f强制删除容器
docker rm -f nginx
3. 命令别名
可以给常用的过于长的命令起别名,方便使用:
#1.修改/root/.bashrc文件
vi /root/.bashrc #或者 vi ~/.bashrc
内容如下: #alias就是别名的意思
# .bashrc# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi#2.执行命令使别名生效
source /root/.bashrc
2.数据卷
1.什么是数据卷
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
以Nginx为例,Nginx中有两个关键目录:
-
html
:放置一些静态资源 -
conf
:放置配置文件
但是,容器运行的Nginx所有的文件都在容器内部,所以必须利用数据卷将两个目录与宿主机目录关联,方便操作。
在上图中:
-
创建了两个数据卷:
conf
、html
-
Nginx容器内部的
conf
目录和html
目录分别与两个数据卷关联。 -
而数据卷
conf
和html
分别指向了宿主机的/var/lib/docker/volumes/conf/_data
目录和/var/lib/docker/volumes/html/_data
目录这样以来,容器内的
conf
和html
目录就 与宿主机的conf
和html
目录关联起来,我们称为挂载。此时,我们操作宿主机的/var/lib/docker/volumes/html/_data
就是在操作容器内的/usr/share/nginx/html/_data
目录。只要我们将静态资源放入宿主机对应目录,就可以被Nginx代理了。注:
/var/lib/docker/volumes
这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data
。
2.数据卷常用命令
docker volume create #创建数据卷
docker volume ls #查看所有数据卷
docker volume rm #删除指定数据卷
docker volume inspect #查看某个数据卷的详情
docker volume prune #清除未使用的数据卷
注:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
案例:Nginx html目录挂载
# 1.首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx# 2.然后查看数据卷
docker volume ls# 3.查看数据卷详情
docker volume inspect html# 4.查看/var/lib/docker/volumes/html/_data目录
ll /var/lib/docker/volumes/html/_data
# 可以看到与nginx的html目录内容一样# 5.进入该目录,并随意修改index.html内容
cd /var/lib/docker/volumes/html/_data
vi index.html# 6.打开页面,查看效果
# 7.进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化
docker exec -it nginx bash
3.挂载本地目录或文件
可以发现,数据卷的目录结构较深,如果我们去操作数据卷目录会不太方便。在很多情况下,我们会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:
# 挂载本地目录
-v 本地目录:容器内目录
# 挂载本地文件
-v 本地文件:容器内文件
注:本地目录或文件必须以 /
或 ./
开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
例如:
-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
-v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
案例:基于宿主机目录实现MySQL数据目录、配置文件、初始化脚本的挂载
-
挂载
/root/mysql/data
到容器内的/var/lib/mysql
目录 -
挂载
/root/mysql/init
到容器内的/docker-entrypoint-initdb.d
目录(初始化的SQL脚本目录) -
挂载
/root/mysql/conf
到容器内的/etc/mysql/conf.d
目录(这个是MySQL配置文件目录)
# 1.在root目录下创建mysql目录,进入到mysql目录中创建目录:data、init、conf
mkdir mysql
cd ~/mysql
mkdir data
mkdir init
mkdir conf# 2.删除原来的MySQL容器
docker rm -f mysql# 3.进入root目录
cd ~# 4.创建并运行新mysql容器,挂载本地目录
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=root \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
mysql# 4.查看root目录,可以发现~/mysql/data目录已经自动创建好了
ls -l mysql# 查看data目录,会发现里面有大量数据库数据,说明数据库完成了初始化
ls -l data# 5.查看MySQL容器内数据
3.镜像
1.镜像结构
镜像之所以能让我们快速跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。因此,自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。
例如:打包镜像分成这么几步
-
准备Linux运行环境(java项目并不需要完整的操作系统,仅仅是基础运行环境即可)
-
安装并配置JDK
-
拷贝jar包
-
配置启动脚本
上述步骤中的每一次操作其实都是在生产一些文件(系统运行环境、函数库、配置最终都是磁盘文件),所以镜像就是一堆文件的集合。
但需要注意的是,镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一id,称为Layer(层)。这样,如果我们构建时用到的某些层其他人已经制作过,就可以直接拷贝使用这些层,而不用重复制作。
2.DockerFile
由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。而这种记录镜像结构的文件就称为Dockerfile。
常用语法 :
FROM #指定基础镜像
ENV #设置环境变量,可在后面指令使用
COPY #拷贝本地文件到镜像的指定目录
RUN #执行Linux的shell命令,一般是安装过程的命令
EXPOSE #指定容器运行时监听的端口,是给镜像使用者看的
ENTRYPOINT #镜像中应用的启动命令,容器运行时调用
例如:我们可以基于Ubuntu基础镜像,利用DockerFile描述镜像结构,也可以直接基于JDK为基础镜像,省略前面的步骤。
3.构建镜像
当写好Dockerfile,准备好jar时,便可以开始构建镜像了。
# 进入镜像目录(假如镜像放在/root/demo下)
cd /root/demo
# 开始构建
docker build -t docker-demo:1.0 .
命令剖析:
-
docker build
:就是构建一个docker镜像 -
-t docker-demo:1.0
:-t
参数是指定镜像的名称(repository
和tag
),名字自定义,版本如果不指定默认是latest。 -
.
: 最后的点是指构建时Dockerfile所在路径,由于我们进入了demo目录,所以用.
代表当前目录,也可以直接指定Dockerfile目录。
# 指定Dockerfile目录
docker build -t docker-demo:1.0 /root/demo
4.网络
默认情况下,所有容器都是以bridge方式连接到Docker的一个虚拟网桥上。
加入自定义网络的容器才可以通过容器名互相访问,Docker的网络操作命令如下:
docker network create #创建一个网络
docker network ls #查看所有网络
docker network rm #删除指定网络
docker network prune #清除未使用的网络
docker network connect #使指定容器连接加入某网络
docker network disconnect #使指定容器连接离开某网络
docker network inspect #查看网络详细信息
六.项目部署
1.部署Java项目
# 1.将打包后的项目和Dockerfile构建项目镜像,不指定tag,则默认为latest
docker build -t 项目名称 .# 2.创建并运行容器,并通过--network将其加入自定义网络,这样才能通过容器名访问mysql
docker run -d --name 项目名称 --network 自定义网络名称 -p 8080:8080 项目镜像名称
2.部署前端
# 1.将项目打包
npm run build# 2.创建nginx的配置文件,完成对前端项目资源代理
# 3.完成挂载并启动nginx
docker run -d \
--name nginx \
-p 端口映射 \
-v /root/nginx/打包的前端项目:/usr/share/nginx/html \
-v /root/nginx/nginx配置文件:/etc/nginx/nginx.conf \
--network 自定义网络名称= \
nginx
3.DockerCompose
DockerCompose通过一个单独的 docker-compose.yml 模板文件(YAML格式)来定义一组相关联的应用容器,帮助我们实现多个相互关联的Docker容器的快速部署。
例如,用docker run部署MySQL的命令如下:
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=root \
-v ./mysql/data:/var/lib/mysql \
-v ./mysql/conf:/etc/mysql/conf.d \
-v ./mysql/init:/docker-entrypoint-initdb.d \
--network hmall
mysql
如果用docker-compose.yml
文件来定义,就是这样:
version: "3.8"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: root
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
networks:
- new
networks:
new:
name: mysqlNet
对比如下:
1.基础语法
docker compose [OPTIONS] [COMMAND]
2.常用命令