🔥博客主页: 【小扳_-CSDN博客】**
❤感谢大家点赞👍收藏⭐评论✍**
文章目录
[1.0 Docker 概述](#1.0 Docker 概述)
[1.1 Docker 主要组成部分](#1.1 Docker 主要组成部分)
[1.2 Docker 安装](#1.2 Docker 安装)
[2.0 Docker 常见命令](#2.0 Docker 常见命令)
[2.1 常见的命令介绍](#2.1 常见的命令介绍)
[2.2 常见的命令演示](#2.2 常见的命令演示)
[3.0 数据卷](#3.0 数据卷)
[3.1 数据卷常见的命令](#3.1 数据卷常见的命令)
[3.2 常见数据卷命令的演示](#3.2 常见数据卷命令的演示)
[3.3 挂载本地目录或文件](#3.3 挂载本地目录或文件)
[4.0 自定义镜像](#4.0 自定义镜像)
[4.1 Dockerfile 文件](#4.1 Dockerfile 文件)
[5.0 网络](#5.0 网络)
[5.1 常见的命令](#5.1 常见的命令)
1.0 Docker 概述
Docker 是一个开源平台,用于自动化应用程序的部署、扩展和管理,采用的是容器化技术。它允许开发者将应用程序及其所有依赖项打包成轻量级、可移植的容器,从而确保无论在何种环境中运行,应用程序都能够保持一致的行为。
1.1 Docker 主要组成部分
Docker 镜像:镜像是一个轻量级、可执行的独立软件包,包含了运行某个软件所需的所有代码、库、环境变量和配置文件。镜像是不可变的,可以从它们创建容器。
Docker 容器:容器是从镜像创建的运行实例,是轻量级的、隔离的执行环境。容器共享宿主操作系统的核心,但相互之间是隔离的。
Docker Hub:这是 Docker 的公共仓库,用户可以在这里存储和分享 Docker 镜像。
1.2 Docker 安装
通过在华为云上安装 Ubuntu 版本的 Docker:
1)若您安装过 Docker,需要先删掉,之后再安装依赖
bashsudo apt-get remove docker docker-engine docker.io sudo apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
2)根据版本不同,运行公钥,添加软件仓库
信任 Docker 的 GPG 公钥:
bashcurl -fsSL https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
对于 amd64 架构的计算机,添加软件仓库:
bashsudo add-apt-repository "deb [arch=amd64] https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
对于树莓派或其它 Arm 架构计算机,请运行:
bashecho "deb [arch=armhf] https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
3)更新索引文件并安装
bashsudo apt-get update sudo apt-get install docker-ce
4)添加镜像
首先执行命令,打开文件:
bashvi /etc/docker/daemon.json
添加镜像信息:
bash{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://dockerhub.timeweb.cloud", "https://huecker.io" ] }
如图:
文件内容输入后,再执行以下命令:
bashsudo systemctl daemon-reload sudo systemctl restart docker
5)最后,测试 Docker 是否安装好
输入以下命令:
bashdocker images
出现的结果为:
这就完成 Dcoker 安装了。
2.0 Docker 常见命令
先来介绍常见的命令,其他不常见的命令可以参考:
Docker 的官方文档:docker | Docker Docs
2.1 常见的命令介绍
1)docker pull:拉取镜像
2)docker push:推送镜像
3)docker images:查看本地镜像
4)docker rmi:删除指定本地镜像
5)docker run:创建容器并运行容器
6)docker stop:停止指定容器
7)docker start:启动指定容器
8)docker restart:重启指定容器
9)docker rm:删除指定容器
10)docker ps:查看容器
11)docker logs:查看容器运行日志
12)docker exec:进入容器
13)docker save:保存镜像到本地压缩文件
14)docker load:加载本地压缩文件到镜像
15)docker inspect:查看容器详情信息
16)docker build:创建本地镜像
用一副图来表示这些命令的关系:
默认情况下,每次重启虚拟机我们都需要手动启动 Docker 和 Docker 中的容器。通过命令可以实现开机自启:
bash# Docker开机自启 systemctl enable docker # Docker容器开机自启 docker update --restart=always [容器名/容器id]
2.2 常见的命令演示
使用 Docker 安装 Nginx 软件为例子:
1)首先从 Docker 中央仓库中拉取 nginx镜像:
bashdocker pull nginx
具体如下:
2)查看镜像:
bashdocker images
具体如下:
成功从 Docker 中央仓库中拉取到 nginx 镜像。
3)创建并运行容器:
bashdocker run -d --name nginx -p 80:80 nginx
命令解析:-d 指在后台运行,--name 指定容器的名字,-p 端口映射,nignx 镜像名
具体如下:
4)查看运行容器:
bashdocker ps
具体如下:
也可以加格式化访问,会更加清爽:
bashdocker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
具体如下:
5)访问网址:
因为 nginx 已经部署到了云服务器了,那么通过 IP:端口号进行访问
具体如下:
成功访问了。
6)停止容器:
bashdocker stop nginx
具体如下:
停止之后,通过查看容器运行情况,发现 nginx 容器已经停止了。
7)启动容器:
bashdocker start nginx
具体如下:
通过启动命令之后,再查看运行容器,发现 nginx 正在运行。
8)查看容器详情:
bashdocker inspect nginx
具体如下:
9)进入容器,查看容器目录
bashdocker exec -it nginx bash
具体如下:
进入到 nginx 容器中,通过 ls 命令查看容器中的目录
额外举个 MySQL 的例子:
通过 docker exec -it mysql bash 进入到 mysql 容器,再通过 mysql -uroot -p 进入到 mysql 控制台
具体如下:
10)强制删除运行中的容器
bashdocker rm nginx -f
具体如下:
删除完之后,查看运行中的容器,发现 nginx 已经被删除了。
11)查看日志
通过 mysql 举个例子
bashdocker logs -f mysql
具体如下:
3.0 数据卷
数据卷(Volume) 是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
因此,容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖都配置都应该与容器解耦。
比如说,MySQL、nginx 容器运行后,如果需要修改其中某些配置该怎么办?这时候,就需要用到数据卷,将宿主机与容器内的配置信息进行映射。
以 nginx 为例,在 nginx 中有两个关键的目录:
1)html:放置一些静态资源。
2)conf:放置配置文件。
利用数据卷将两个目录与宿主机目录关联,如图:
在上图中:
我们创建了两个数据卷: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。
3.1 数据卷常见的命令
1)docker volume create:创建数据卷
2)docker volume ls:查看所有数据卷
3)docker volume inspect:查看某个数据卷的详情
4)docker volume rm:删除指定数据卷
5)docker volume prune:清除数据卷
注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
3.2 常见数据卷命令的演示
以 niginx 为例子,将容器中的 /usr/share/nginx/html 目录挂载到宿主机中。
1)首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷:
bashdocker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
具体如下:
2)查看数据卷:
bashdocker volume ls
具体如下:
可以通过修改宿主机中的 html 来修改配置,从而会自动映射到 nginx 容器中的配置:
修改之前:
修改宿主机的 html:
此时,宿主机中的 index.html 文件被修改了,观察是否映射到容器中的 index.html 文件:
发现已经被修改了,但是修改文字对不上号,这可能是字符集导致的乱码。
使用英文再测试一遍:
宿主机中的 index.html:
再来访问 nginx
因此,宿主机中的 index.html 与容器中的 index.html 成功完成了映射。
3)查看数据卷详情:
bashdocker volume inspect html
具体如下:
3.3 挂载本地目录或文件
可以发现,数据卷的目录结构较深,如果我们去操作数据卷目录会不太方便。在很多情况下,我们会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:
bash# 挂载本地目录 -v 本地目录:容器内目录 # 挂载本地文件 -v 本地文件:容器内文件
注意:本地目录或文件必须以 / 或 ./ 开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
例如:
bash-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷 -v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
使用 mysql 为例,将 mysql 容器中的 /var/lib/mysql 文件挂载到 ./mysql/data 本地目录。
bashdocker run -d \ --name mysql \ -p 3306:3306 \ -e TZ=Asia/Shanghai \ -e MYSQL_ROOT_PASSWORD=123 \ -v ./mysql/data:/var/lib/mysql \ mysql
具体如下:
本地目录与容器中的 /var/lib/mysql 文件挂载成功了,因此可以通过修改本地目录的数据,从而实现对容器中的 mysql 数据进行修改。
4.0 自定义镜像
要想自己构建镜像,必须先了解镜像结构。镜像之所以能让我们快速跨操作系统部署应用而忽略器运行环境、配置,就是因为镜像中包含了程序运行需要的系统函数库、环境、配置、依赖。
因此,自定义镜像本质就是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成。
举个例子,从 0 部署一个 Java 应用,大概的流程:
1)准备一个 linux 服务(CentOS 或者 Ubuntu 均可)
2)安装并配置 JDK
3)上传 Jar 包
4)运行 Jar 包
那因此,打包镜像也是分为这么几步:
1)准备 Linx 环境,Java 项目并不需要完整的操作系统,仅仅是基础运行环境即可。
2)安装并配置 JDK 。
3)拷贝 Jar 包。
4)配置启动脚本。
上述步骤中每一个操作其实都是在生产一些文件,系统运行环境、函数库、配置最终都是磁盘文件,所以镜像就是一堆文件的集合。
但是需要注意的是,镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一 id,称为 Layer(层)。这样,在构建一些重复的层,就不需要重复拷贝这些层了。
4.1 Dockerfile 文件
由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以 Docker 就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给 Docker 去执行即可。
而这种记录镜像结构的文件就称为 Dockerfile,其对应的语法可以参考官方文档:Dockerfile reference | Docker Docs
其中的语法比较多,比较常用的有:
1)FROM:指定基础镜像。
2)ENV:设置环境变量,可在后面指令使用。
3)COPY:拷贝本地文件到镜像的指定目录。
4)RUN:执行 Linux 的 shell 命令,一般是安装过程的命令。
5)EXPOSE:指定容器运行时监听的端口,是给镜像使用者看的。
6)ENTRYPOINT:镜像中应用的启动命令,容器运行时调用。
例如,要基于 Ubuntu 镜像来构建一个 Java 应用,其 Dockerfile 内容如下:
# 指定基础镜像 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"]
思考一下:以后我们会有很多很多 java 项目需要打包为镜像,他们都需要 Linux 系统环境、JDK 环境这两层,只有上面的3层不同(因为 jar 包不同)。如果每次制作 java 镜像都重复制作前两层镜像,是不是很麻烦。
所以,就有人提供了基础的系统加JDK环境,我们在此基础上制作 java 镜像,就可以省去 JDK 的配置了:
# 基础镜像 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"]
因此,我们只需要准备 JDK 的基础镜像和 jar 包即可。
举个例子:
1)现在准备好了 Dockerfile 文件和 jar 包、jdk.jar
先将 jdk.jar 的基础镜像加载到镜像中:
docker load -i jdk.tar
具体如下:
2)接着指定命令:
进入 demo 目录:
再执行该命令:
# 直接指定Dockerfile目录 docker build -t docker-demo .
命令说明:
docker build : 就是构建一个 docker 镜像
-t docker-demo :-t 参数是指定镜像的名称(repository 和 tag)
. : 最后的点是指构建时 Dockerfile 所在路径,由于我们进入了 demo 目录,所以指定的是 . 代表当前目录,也可以直接指定 Dockerfile 目录。
因为 Dockerfile 就在当前目录下,直接使用 . 来声明 Dockerfile 的位置。
具体如下:
3)查看镜像:
具体如下:
4)创建并运行容器:
docker run -d --name dd -p 8080:8080 docker-demo
具体如下:
运行之后,查看运行容器
5)访问容器:
5.0 网络
假设创建了一个 Java 项目的容器,而 Java 项目往往需要访问其它各种中间件,例如 MySQL、Redis 等。现在,我们的容器之间能否互相访问呢?我们来测试一下:
首先,我们查看下 MySQL 容器的详细信息,重点关注其中的网络 IP 地址:
# 1.用基本命令,寻找Networks.bridge.IPAddress属性 docker inspect mysql # 也可以使用format过滤结果 docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' mysql # 得到IP地址如下: 172.17.0.2 # 2.然后通过命令进入dd容器 docker exec -it dd bash # 3.在容器内,通过ping命令测试网络 ping 172.17.0.2 # 结果 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.053 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.058 ms
但是,容器的网络 IP 其实是一个虚拟的 IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个 IP,而在部署时很可能 MySQL 容器的IP会发生变化,连接会失败。
所以,我们必须借助于 docker 的网络功能来解决这个问题。
5.1 常见的命令
1)docker network create:创建一个网络
2)docker network ls:查看所有网络
3)docker network rm:删除指定网络
4)docker network prune:清除未使用的网络
5)docker network connect:使指定容器连接加入某网络
6)docker network disconnect:使指定容器连接离开某网络
7)docker network inspect:查看网络详情信息
自定义网络演示:
首先,创建一个网络:
docker network create xbs
具体如下:
接着查看网络:
docker network ls
具体如下:
再接着详细了解 xbs 网络:
docker network inspect xbs
具体如下:
网关为:172.18.0.1
将 mysql 加入到该网络中:
docker network connect xbs mysql
具体如下:
查看 mysql 网络详情:
docker inspect mysql
具体如下:
此时 mysql 容器中的网关为 172.18.0.1,IP 为 172.18.0.2 。
配置完 mysql 容器之后,只要在该网段中的所有容器,都可以根据容器名进行相互访问。
接着将 Java 项目的容器加入该网段:
docker network connect xbs dd
具体如下:
查看详情信息
网关为 172.18.0.1,Java 项目的 IP 为 172.18.0.4 。因此,dd 容器可以与 mysql 容器进行相互访问,联通的。
dd 容器与 mysql 容器尝试进行拼接:
docker exec -it dd bash
具体如下:
在加入了同一个网段之后,只需要通过访问容器名就可以实现 dd 容器与 mysql 容器进行连通。
总结:
1)在自定义网络中,可以给容器其多个别名,默认的别名是容器名本身。
2)在同一个自定义网络中的容器,可以通过别名互相访问。
3)现在无需记住 IP 地址也可以实现容器互联。