# 02_Docker快速入门到项目部署(二)
# 02_Docker快速入门到项目部署(二)
## 一、Docker基础-命令别名
### 1、给常用Docker命令起别名,方便我们访问 vim ~/.bashrc
修改 /root/.bashrc文件: vi /root/.bashrc 内容如下:
```bash
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias cls='clear'
alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
alias dis='docker images'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
```
### 2、使用别名生效 source ~/.bashrc
```bash
source ~/.bashrc
```
### 3、示例:
## 二、Docker基础-数据卷挂载
### 1、docker数据卷引入
1)容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,我们要读写容器内的文件非常不方便。
2)思考几个问题:
* 如果要升级MySQL版本,需要销毁旧容器,那么数据岂不是跟着被销毁了?
* MySQL、Nginx容器运行后,如果要修改其中的某些配置该怎么办?
* 想要让Nginx代理静态资源怎么办?
3)因此,容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖的配置都应该与容器解耦。
### 2、什么是数据卷
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
### 3、以Nginx为例,Nginx中有两个关键的目录:
* html:放置一些静态资源
* conf:放置配置文件
1)如果要让Nginx代理静态资源,最好是放到html目录;如果要修改Nginx的配置,最好是找到conf下的nginx.conf文件。
2)但容器运行的Nginx所有的文件都在容器内部。所以我们必须利用数据卷将两个目录与宿主机目录关联,方便我们操作。如图:
3)创建了两个数据卷:conf、html
让Nginx容器内部的conf目录和html目录分别与两个数据卷关联。
而数据卷conf和html分别指向了宿主机的/var/lib/docker/volumes/conf/_data目录和/var/lib/docker/volumes/html/_data目录。
4)挂载
容器内的conf和html目录就 与宿主机的conf和html目录关联起来,我们称为挂载。此时,操作宿主机的/var/lib/docker/volumes/html/_data就是在操作容器内的/usr/share/nginx/html/_data目录。只要将静态资源放入宿主机对应目录,就可以被Nginx代理了。
### 4、数据卷相关命令
命令 | 说明 |
docker volume create | 创建数据卷 |
docker volume ls | 查看所有数据卷 |
docker volume rm | 删除指定数据卷 |
docker volume inspect | 查看某个数据卷详情 |
docker volume prune | 清除数据卷 |
### 5、注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
### 6、案例1-利用Nginx容器部署静态资源
1)需求:
* 创建Nginx容器,修改nginx容器内的html目录下的index.html文件,查看变化。
* 将静态资源部署到nginx的html目录。
2)提示
在执行docker run命令时,使用 -v 数据卷:容器内目录 可以完成数据卷挂载
当创建容器时,如果挂载了数据卷且数据卷不存在,会自动创建数据卷
3)演示一下nginx的html目录挂载
```bash
# 先删除原来创建的 nginx 容器
docker rm -f nginx
# 1.首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
# 2.然后查看数据卷
docker volume ls
# 结果
DRIVER VOLUME NAME
local 2b97edfe89a697ccb1e2f93c4f520c420f5ed3d7cfa108913cd761dc1b1fb480
local 012b50ffc87e4fbd6dcf6eae976941382bc1e582adcfa6025488fb70cb67c574
local 71cf4ae267c6096f6acad5ebf0cb6a89799b0197e4e87e77829a52a661db6916
local fe707cb1f3ba76c5b18d730d94dbfccf8432da85124889febe28d4183ff75aa3
local html
# 3.查看数据卷详情
docker volume inspect html
# 结果
[
{
"CreatedAt": "2025-01-19T13:45:45+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/html/_data",
"Name": "html",
"Options": null,
"Scope": "local"
}
]
# 4.查看/var/lib/docker/volumes/html/_data目录
ll /var/lib/docker/volumes/html/_data
# 可以看到与nginx的html目录内容一样,结果如下:
总用量 8
-rw-r--r--. 1 root root 497 11月 26 23:55 50x.html
-rw-r--r--. 1 root root 615 11月 26 23:55 index.html
# 5.进入该目录,并随意修改index.html内容
cd /var/lib/docker/volumes/html/_data
vi index.html
# 6.打开页面,查看效果,如:http://192.168.3.29
# 7.进入容器内部,查看/usr/share/nginx/html目录内的文件是否变化
docker exec -it nginx bash
```
### 7、docker 数据卷总结
1)什么是数据卷?
数据卷是一个虚拟目录,它将宿主机目录映射到容器内目录,方便我们操作容器内文件,或者方便迁移容器产生的数据。
2)如何挂载数据卷?
在创建容器时,利用 -v 数据卷名:容器内目录完成挂载。
容器创建时,如果发现挂载的数据卷不存在时,会自动创建。
3)数据卷的常见命令有哪些?
docker volume ls: 查看数据卷
docker volume rm: 删除数据卷
docker volume inspect: 查看数据卷详情
docker volume prune: 删除未使用的数据卷
### 8、示例:
## 三、Docker基础-本地目录挂载
### 1、MySQL的匿名数据卷
```bash
# 1.查看MySQL容器详细信息
docker inspect mysql
# 2.关注其中.Config.Volumes部分和.Mounts部分
# 3.第一是.Config.Volumes部分
{
"Config": {
// ... 略
"Volumes": {
"/var/lib/mysql": {}
}
// ... 略
}
}
# 4.发现这个容器声明了一个本地目录,需要挂载数据卷,但是数据卷未定义。这就是匿名卷。
# 5.再看结果中的.Mounts部分
{
"Mounts": [
{
"Type": "volume",
"Name": "29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f",
"Source": "/var/lib/docker/volumes/29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f/_data",
"Destination": "/var/lib/mysql",
"Driver": "local",
}
]
}
```
### 2、MySQL的匿名数据卷 几个关键属性:
Name:数据卷名称。由于定义容器未设置容器名,这里的就是匿名卷自动生成的名字,一串hash值。
Source:宿主机目录。
Destination : 容器内的目录。
1)上述配置是将容器内的/var/lib/mysql这个目录,与数据卷29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f挂载。
2)于是在宿主机中就有了/var/lib/docker/volumes/29524ff09715d3688eae3f99803a2796558dbd00ca584a25a4bbc193ca82459f/_data这个目录。这就是匿名数据卷对应的目录,其使用方式与普通数据卷没有差别。
### 3、挂载本地目录或文件
1)可以发现,数据卷的目录结构较深,如果去操作数据卷目录会不太方便。在很多情况下,我们会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:
```bash
# 挂载本地目录
-v 本地目录:容器内目录
# 挂载本地文件
-v 本地文件:容器内文件
```
2)注意:本地目录或文件必须以 / 或 ./开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。例如:
```bash
-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
-v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
```
### 4、案例2-mysql容器的数据挂载
1)需求:
* 查看mysql容器,判断是否有数据卷挂载。
* 基于宿主机目录实现MySQL数据目录、配置文件、初始化脚本的挂载(查阅官方镜像文档)。
挂载/root/mysql/data到容器内的/var/lib/mysql目录。
挂载/root/mysql/init到容器内的/docker-entrypoint-initdb.d目录。
挂载/root/mysql/conf到容器内的/etc/mysql/conf.d目录。
2)提示
* 在执行docker run命令时,使用 -v 本地目录 : 容器内目录 可以完成本地目录挂载。
* 本地目录必须以“/”或 "./" 开头,如果直接以名称开头,会被识别为数据卷而非本地目录。如下:
-v mysql : /var/lib/mysql 会被识别为一个数据卷叫mysql
-v ./mysql : /var/lib/mysql 会被识别为当前目录下的mysql目录
3)演示 mysql 本地目录挂载:
```bash
# 1.删除原来的MySQL容器
docker rm -f mysql
# 2.进入root目录,创建新目录和脚本文件
cd ~
# 2.1 创建新目录
pwd
/root
mkdir mysql
cd mysql/
mkdir data
mkdir conf
mkdir init
# 2.2 拷贝sql脚本 hmall.sql和配置文件 hm.cnf
cat /root/mysql/conf/hm.cnf
[client]
default_character_set=utf8mb4
[mysql]
default_character_set=utf8mb4
[mysqld]
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
init_connect='SET NAMES utf8mb4'
# 3.创建并运行新mysql容器,挂载本地目录
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
-v /root/mysql/data:/var/lib/mysql \
-v /root/mysql/conf:/etc/mysql/conf.d \
-v /root/mysql/init:/docker-entrypoint-initdb.d \
mysql
# 4.查看root目录,可以发现~/mysql/data目录已经自动创建好了
ls -l mysql
# 结果:
conf data init mysql
# 查看data目录,会发现里面有大量数据库数据,说明数据库完成了初始化
ls -l data
# 5.查看MySQL容器内数据
# 5.1.进入MySQL
docker exec -it mysql mysql -uroot -p123
# 5.2.查看编码表
show variables like "%char%";
# 5.3.结果,发现编码是utf8mb4没有问题
# 6.查看数据
# 6.1.查看数据库
show databases;
# 6.2.切换到hmall数据库
use hmall;
# 6.3.查看表
show tables;
```
### 5、示例:
## 四、Docker基础-Dockerfile语法
### 1、镜像结构
1)要想自己构建镜像,必须先了解镜像的结构。
2)镜像之所以能快速跨操作系统部署应用而忽略其运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。
3)因此,自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。
4)从0部署一个Java应用,大概流程是这样:
* 准备一个linux服务(CentOS或者Ubuntu均可)
* 安装并配置JDK
* 上传Jar包
* 运行jar包
5)因此,打包镜像也是分成这么几步:
* 准备Linux运行环境(java项目并不需要完整的操作系统,仅仅是基础运行环境即可)
* 安装并配置JDK
* 拷贝jar包
* 配置启动脚本
### 2、Layer(层):镜像就是一堆文件的集合。
镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一id,称为Layer(层)。
### 3、镜像结构示意图
### 4、dockerfile
1)Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。Docker可以根据Dockerfile构建镜像。
2)这种记录镜像结构的文件就称为Dockerfile,其对应的语法
指令 | 说明 | 示例 |
FROM | 指定基础镜像 | FROM centos:6 |
ENV | 设置环境变量,可在后面指令使用 | ENV key value |
COPY | 拷贝POSE文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN yum install gcc |
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT iava -iar xx.iar |
3)更多对应的语法可以参考官方文档:
https://docs.docker.com/engine/reference/builder/
## 五、Docker基础-自定义镜像
### 1、例如:要基于Ubuntu镜像来构建一个Java应用,其Dockerfile内容如下:
```bash
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装JDK
RUN cd $JAVA_DIR \
&& tar -xf ./jdk8.tar.gz \
&& mv ./jdk1.8.0_144 ./java8
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
# 指定项目监听的端口
EXPOSE 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
```
### 2、使用别人制作的基础的系统加JDK环境,制作java镜像,可以省去JDK的配置而简化其Dockerfile内容如下:
```bash
# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
```
### 3、dockerfile 构建镜像步骤:
1)准备好了一个demo项目及对应的Dockerfile 文件。
把 docker-demo.jar包以及Dockerfile拷贝到虚拟机的 /root/demo目录
```bash
# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
```
2)把 jdk.tar 包,上传到虚拟机的 /root/demo/ 目录中,并解压成本地镜像(就不需要下载jdk镜像了),也可以忽略此步,下载摘取镜像。
```bash
dd /root/demo/
docker load -i jdk.tar
```
3)构建镜像
```bash
cd /root/demo/
docker build -t docker-demo .
```
4)创建容器
```bash
docker run -d --name dzs168 -p 8080:8080 docker-demo
```
5)查看容器(使用之前配置的别名)
```bash
dps
```
6)查看日志
```bash
docker logs -f dzs168
```
### 4、dockerfile 总结
1)镜像的结构是怎样的?
镜像中包含了应用程序所需要的运行环境、函数库、配置、以及应用本身等各种文件,这些文件分层打包而成。
2)Dockerfile是做什么的?
Dockerfile就是利用固定的指令来描述镜像的结构和构建过程,这样Docker才可以依次来构建镜像。
3)构建镜像的命令是什么?
docker build -t 镜像名 Dockerfile目录。
### 5、示例:http://192.168.3.29:8080/hello/count
`上一节关联链接请点击:`