一、Docker简介
Docker 是一种开源的容器化技术,能够将应用及其依赖打包进轻量级、可移植的容器中,实现快速部署和跨平台运行。
即:Docker是一个快速构建、运行、管理应用的工具。
1.1 镜像和容器
当我们利用Docker安装应用时,Docker会自动搜索并下载应用镜像(image)。镜像不仅包含应用本身,还包含应用运行所需要的环境、配置、系统函数库。Docker会在运行镜像时创建一个隔离环境,称为容器(container)。
镜像仓库:存储和管理镜像的平台,Docker官方维护了一个公共仓库:Docker Hub。
下图所示为docker、容器、镜像和镜像仓库的逻辑关系:
容器(Container)是一种轻量级的、可执行的软件包,它将代码和环境打包在一起,确保应用在任何地方都能以相同的方式运行。容器是独立且隔离的,运行在宿主机上,共享操作系统内核,但与其他容器相互隔离。
镜像(Image)是容器运行的模板,包含了运行容器所需的代码、运行时、系统工具、系统库等。镜像是只读的,可以被多个容器实例共享,确保了环境的一致性。
仓库(Repository)是存放容器镜像的场所,可以是本地的也可以是远程的。常用的远程仓库包括 Docker Hub 和私有仓库。开发者将镜像推送到仓库中,其他用户可以从仓库中拉取镜像来创建和运行容器。
Docker是做什么的?
- Docker可以帮助我们下载应用镜像,创建并运行镜像的容器,从而快速部署应用。
什么是镜像?
- 将应用所需的函数库、依赖、配置等与应用一起打包得到的就是镜像。
什么是容器?
- 为每个镜像的应用进程创建的隔离运行环境就是容器。
什么是镜像仓库?
- 存储和管理镜像的服务就是镜像仓库,DockerHub是目前最大的镜像仓库,其中包含各种常见的应用镜像。
二、Docker安装
2.1 虚拟机系统准备
见【centos虚拟机安装及问题解决】一文。
我最后用的系统,centos7
2.2 卸载旧版Docker
首先如果系统中已经存在旧的Docker,则先卸载:
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine \
docker-selinux
我的虚拟机上没有需要删除的docker相关的包。
2.3 配置Docker的yum源
2.3.1 yum工具包安装
首先要安装一个yum工具。
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
2.3.2 配置yum源
安装成功后,执行命令,配置Docker的yum源(已更新为阿里云源):
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
sudo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
sudo sed -i ‘s+download.docker.com+mirrors.aliyun.com/docker-ce+’ /etc/yum.repos.d/docker-ce.repo
命令解释:
sed: 调用sed工具,它是一个流编辑器,用于对文本进行过滤和替换。-i: 选项告诉sed直接在文件中进行编辑,而不是输出到标准输出(即终端)。这会导致原文件被修改。's+download.docker.com+mirrors.aliyun.com/docker-ce+': 这是一个sed的替换命令,它指示sed执行以下操作:
s: 表示替换(substitute)。+: 在sed中用作分隔符,这里它替代了默认的空格分隔符,因为默认的空格在URL中会出现,使用+可以避免这种情况。download.docker.com: 这是要被替换的字符串,即原始的Docker镜像源地址。mirrors.aliyun.com/docker-ce: 这是替换后的字符串,即阿里云的Docker镜像源地址。/etc/yum.repos.d/docker-ce.repo: 指定了要编辑的文件路径。这个文件是Docker CE(社区版)的YUM仓库配置文件。
2.3.3 更新yum,建立缓存
sudo yum makecache fast
2.4 安装Docker
yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
2.5 启动和校验安装是否成功
# 查看docker状态
systemctl status docker
# 启动Docker
systemctl start docker
# 停止Docker
systemctl stop docker
# 重启
systemctl restart docker
# 设置开机自启
systemctl enable docker
# 执行docker ps命令,如果不报错,说明安装启动成功
docker ps
2.6 配置镜像加速
阿里云docker镜像加速:
https://help.aliyun.com/zh/acr/user-guide/accelerate-the-pulls-of-docker-official-images
2.6.1 获取镜像加速器地址
- 登录容器镜像服务控制台。
- 在左侧导航栏选择*镜像工具** > **镜像加速器*
- 在镜像加速器页面获取加速器地址。
2.6.2 配置镜像加速器
Docker和Containerd的镜像加速器配置方法有所不同。您可以根据具体情况选择合适的配置方式。
可以先使用docker --version查看Docker的版本,然后根据实际情况选择不同的配置方式。
新版本Docker(1.10及以上)
创建并编辑/etc/docker/daemon.json文件(如果文件不存在,则创建):
{
"registry-mirrors": ["<镜像加速器地址>"]
}
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxxxxx.aliyuncs.com"]
}
EOF
然后重启Docker Daemon。
sudo systemctl daemon-reload
sudo systemctl restart docker
三、Docker快速入门(一键部署mysql)
3.1 一键部署mysql
docker run -d --name ms -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123 mysql
命令解读:
docker run :创建并运行一个容器,**-d** 是让容器在后台运行
–name mysql :给容器起个名字,必须唯一
-p 3306:3306 :设置端口映射 ,<宿主机端口>:<容器端口>
-e KEY=VALUE :是设置环境变量
mysql :指定运行的镜像的名字
3.2 镜像加速问题解决
问题解决:
网上有很多原因解释,一是说因为没有配置镜像加速,可是刚在前面配置过,并且也重启了docker。
尝试更换为如下的地址:
"registry-mirrors":["https://docker.mirrors.ustc.edu.cn"]还是不行。
继续鼓捣这个daemon.json
{ "registry-mirrors" : [ "https://mirror.ccs.tencentyun.com", "http://registry.docker-cn.com", "http://docker.mirrors.ustc.edu.cn", "http://hub-mirror.c.163.com" ], "insecure-registries" : [ "registry.docker-cn.com", "docker.mirrors.ustc.edu.cn" ], "debug" : true, "experimental" : true }{ "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/","https://hub-mirror.c.163.com","https://registry.docker-cn.com"], "insecure-registries": ["10.0.0.12:5000"] }还是不行。
![]()
发现是域名解析的问题,然后尝试追加网卡配置:
vim /etc/sysconfig/network-scripts/ifcfg-ens33![]()
![]()
还是无法ping通。
![]()
- 使用dig获取ip
yum install bind-utils dig @114.114.114.114 registry-1.docker.io dig @8.8.8.8 registry-1.docker.io
dig到的ip208.43.170.231…ping不通。
docker info查看信息,镜像仓库已经配置成功,网页访问一下各个地址,发现都访问不了。
最终通过不断尝试和查找资料找到一种可行的方法,直接在镜像名前面加可用的仓库地址(这个需要不断搜集更新,时不时就有可能被墙)。
最终解决:
1)收集仓库地址,http访问测试连通性并配置。
![]()
https://docker.1panel.dev/tee /etc/docker/daemon.json <<EOF { "registry-mirrors": ["https://docker.1panel.dev"] } EOFsystemctl daemon-reload systemctl restart docker2)拉取镜像的时候添加路径
按照上面的过程操作之后,还是会报错。
这时候添加路径进行尝试。
![]()
![]()
说明还是挂掉了。那么就需要继续找新的能用的镜像仓库。
https://www.cnblogs.com/Nine4Cool/p/18499621
https://blog.csdn.net/llc580231/article/details/139979603
最后下面一些可用的镜像仓库地址:
https://docker.m.daocloud.io https://docker.zhai.cm![]()
注意:单次指定从某个仓库拉取镜像,指定
域名/library/mysql。
仍然会拉取失败。。。。。。。
用https://docker.zhai.cm 拉取成功。
所以进行配置:
sudo tee /etc/docker/daemon.json <<EOF { "registry-mirrors": ["https://docker.zhai.cm"] } EOF systemctl daemon-reload systemctl restart docker再尝试拉取一下nginx镜像。
![]()
成功拉取得。
所以核心中的核心就是拿到流畅可用的镜像仓库地址。
- 拉取镜像的时候加前缀
docker pull m.daocloud.io/docker.io/library/node:22
3.3 访问测试
四、Docker命令基础
4.1 镜像命名规范
镜像名称一般分两部分组成:[repository]:[tag]。
其中repository就是镜像名
tag是镜像的版本
在没有指定tag时,默认是latest,代表最新版本的镜像。
4.2 命令概述
Docker最常见的命令就是操作镜像、容器的命令,详见官方文档: https://docs.docker.com/
4.3 案例练习
在DockerHub中搜索Nginx镜像,查看镜像的名称
拉取Nginx镜像:docker pull 镜像名
查看本地镜像列表:docker images
创建并运行Nginx容器:docker run -d
查看容器: docker images
停止容器:docker stop
再次启动容器:docker start
进入Nginx容器:docker exec -it
删除容器:docker rm
4.4 命令别名
docker ps的输出可读性较差,如下图所示:
为了简化docker ps命令的输出,通常会用如下的命令来查看容器信息:
docker ps --format "table {{.ID}}\t {{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
命令冗长不便于记忆,可以在~/.bashrc中命名一个别名。编辑~/.bashrc,添加如下内容(顺便把docker images也简化了):
vim ~/.bashrc
-a 参数是为了显示那些停止运行但没有被删除的容器。
保存退出之后,执行
source ~/.bashrc
测试:
五、数据卷
5.1 数据卷
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
如图所示,通过创建数据卷可以实现宿主机目录和容器目录的同步读写操作。
5.2 数据卷相关的命令
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker volume create | 创建数据卷 | docker volume create |
| docker volume ls | 查看所有数据卷 | docker volume ls |
| docker volume rm | 删除指定数据卷 | docker volume rm |
| docker volume inspect | 查看某个数据卷的详情 | docker volume inspect |
| docker volume prune | 清除数据卷 | docker volume prune |
5.3 案例一(卷名挂载)
5.3.1 案例描述
- 创建Nginx容器,修改nginx容器内的html目录下的index.html文件,查看变化
尝试进入容器进行修改,发现vi命令不存在。这是因为镜像一般都是最小化安装,并没有提前预置各种工具。
- 将静态资源部署到nginx的html目录
想从宿主机拷贝资源到容器中该怎么办?
5.3.2 案例解决
在执行docker run命令时,使用 -v 数据卷:容器内目录可以完成数据卷挂载
当创建容器时,如果挂载了数据卷且数据卷不存在,会自动创建数据卷
下图为案例5.1的解决,在docker run 创建容器的时候,-v指定数据卷。
回顾:
什么是数据卷?
- 数据卷是一个虚拟目录,它将宿主机目录映射到容器内目录,方便我们操作容器内文件,或者方便迁移容器产生的数据。
如何挂载数据卷?
- 在创建容器时,利用 -v 数据卷名:容器内目录完成挂载
- 容器创建时,如果发现挂载的数据卷不存在时,会自动创建
数据卷的常见命令有哪些?
- docker volume ls: 查看数据卷
- docker volume rm: 删除数据卷。
- docker volume inspect: 查看数据卷详情。
- docker volume prune: 删除未使用的数据卷。
5.4 案例二(宿主机目录挂载)
5.4.1 案例描述
需求:
查看mysql容器,判断是否有数据卷挂载
基于宿主机目录实现MySQL数据目录、配置文件、初始化脚本的挂载(查阅官方镜像文档)
①挂载/root/mysql/data到容器内的/var/lib/mysql目录
②挂载/root/mysql/init到容器内的/docker-entrypoint-initdb.d目录,提前准备的SQL脚本
③挂载/root/mysql/conf到容器内的/etc/mysql/conf.d目录,提前准备的配置文件。
5.4.2 案例解决
在执行docker run命令时,使用 -v 本地目录 : 容器内目录 可以完成本地目录挂载
本地目录必须以“**/”或 “./**” 开头,如果直接以名称开头,会被识别为数据卷而非本地目录
-v mysql:/var/lib/mysql 会被识别为一个数据卷叫mysql
-v ./mysql:/var/lib/mysql 会被识别为当前目录下的mysql目录
测试数据成功生成,说明我们挂载的本地init目录中的sql脚本被成功执行。
六、自定义镜像
6.1 镜像结构
镜像就是包含了程序运行的系统函数库、应用程序、运行配置等文件的文件包。构建镜像的过程其实就是把上述文件打包的过程。
镜像结构:
6.2 Dockerfile
Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。将来Docker可以根据Dockerfile帮我们构建镜像。常见指令如下:
| 指令 | 说明 | 示例 |
|---|---|---|
| FROM | 指定基础镜像 | FROM centos:6 |
| ENV | 设置环境变量,可在后面指令使用 | ENV key value |
| COPY | 拷贝本地文件到镜像的指定目录 | COPY ./jre11.tar.gz /tmp |
| RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN tar -zxvf /tmp/jre11.tar.gz && EXPORTS path=/tmp/jre11:$path |
| EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
| ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |
更新详细语法说明,请参考官网文档: https://docs.docker.com/engine/reference/builder
- 示例:
我们可以基于Ubuntu基础镜像,利用Dockerfile描述镜像结构。
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 安装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
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
我们可以基于Ubuntu基础镜像,利用Dockerfile描述镜像结构,也可以直接基于JDK为基础镜像,省略前面的步骤:
6.3 构建镜像
# 基础镜像
FROM openjdk:11.0-jre-buster
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
当编写好了Dockerfile,可以利用下面命令来构建镜像:
docker build -t myImage:1.0 .
-t :是给镜像起名,格式依然是repository:tag的格式,不指定tag时,默认为latest
. :是指定Dockerfile所在目录,如果就在当前目录,则指定为”.”
6.3 构建镜像并运行(EX)
6.3.1 构建镜像
注意镜像名称不能有大写字母。
获取基础镜像时报错。
单独拉取一下openjdk:11.0-jre-buster镜像。
然后重新运行构建镜像的命令。
6.3.2 运行容器
6.3.3 访问测试
成功访问到容器内的应用。
总结
- 镜像的结构是怎样的?
镜像中包含了应用程序所需要的运行环境、函数库、配置、以及应用本身等各种文件,这些文件分层打包而成。
- Dockerfile是做什么的?
Dockerfile就是利用固定的指令来描述镜像的结构和构建过程,这样Docker才可以依次来构建镜像。
- 构建镜像的命令是什么?
docker build -t 镜像名 Dockerfile目录
七、Docker网络
默认情况下,所有容器都是以bridge方式连接到Docker的一个虚拟网桥上:
docker inspect 来查看容器的网络配置。
网络,加入自定义网络的容器可以通过容器名互相访问,Docker的网络操作命令如下:
| 命令 | 说明 | 文档地址 |
|---|---|---|
| docker network create | 创建一个网络 | docker network create |
| docker network ls | 查看所有网络 | docker network ls |
| docker network rm | 删除指定网络 | docker network rm |
| docker network prune | 清除未使用的网络 | docker network prune |
| docker network connect | 使指定容器连接加入某网络 | docker network connect |
| docker network disconnect | 使指定容器连接离开某网络 | docker network disconnect |
| docker network inspect | 查看网络详细信息 | docker network inspect |
- 可以在docker run 的时候通过 –networks 指定网络名。
八、分容器项目部署
创建网络:
[root@localhost ~]# docker network create heima
9a85558bc3ab76e21390a914afb454051467c183fa972c5e0782efcdab286538
后续创建的容器使用–networks heima指定网络名。
8.1 部署mysql数据库容器
- 注意保持java后端项目数据库的配置和mysql容器本身配置的连通性。
mysql数据库容器的容器名mysql,密码123。只有这样,在网络连通的前提下,才能保证java后端应用能够成功访问到mysql容器。
docker run -d --name mysql -p 3306:3306 -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 --network heima mysql
8.2 部署Java后端应用容器
- 注意保持java后端项目数据库的配置和mysql容器本身配置的连通性。
用idea打开项目,通过maven把需要的库都安装一下,然后打包成jar包(注意跳过单元测试)。
dockerfile:
# 基础镜像
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 hm-service.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
上传到目标机器中,然后制作镜像。
制作镜像:
docker build -t hmall .
启动容器:
[root@localhost hm-service]# docker run -d --name hmall -p 8080:8080 --network heima hmall
e5c900979c64be115676c294396e7ebc4deafdcba44c91ac49cc172cddaceed9
[root@localhost hm-service]# dps
CONTAINER ID IMAGE PORTS STATUS NAMES
e5c900979c64 hmall 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp Up 2 seconds hmall
a26885a896d6 mysql 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp Up 16 minutes mysql
1266a9029269 nginx:latest 0.0.0.0:8000->80/tcp, :::8000->80/tcp Up 23 hours nginxOnCentOS
docker logs -f hmall 查看日志。
访问测试:
访问http://192.168.155.34:8080/search/list?pageNo=1&pageSize=5 接口报错:
进入hmall容器ping mysql容器,可以连通。
但是mysql容器中没有ping、ipaddr之类的命令。
网络结构:
虚拟网卡:172.18.0.1
mysql:172.18.0.2
hmall:172.18.0.3
登入mysql容器,执行mysql登录命令:mysq -uroot -p 发现密码是123.com才能登录。但是之前创建数据库的时候明明使用-e参数配置的密码是123呀,可能是挂在时没有清空宿主机data目录(目录里面观察到有一些鉴权的组件)的原因。
清空data目录之后,重新安装mysql:
[root@localhost hm-service]# docker run -d --name hmall -p 8080:8080 --network heima hmall
进入容器用123的密码成功登录。
继续访问测试页面,成功获取到后台的数据。
至此,后端应用容器和数据库容器成功部署。
8.3 部署前端nginx容器
创建一个新的nginx容器,将提供的nginx.conf、html目录与容器挂载。
[root@localhost nginx]# docker run -d --name nginx -p 18080:18080 -p 18081:18081 --network heima -v /root/nginx/html/:/usr/share/nginx/html -v /root/nginx/nginx.conf:/etc/nginx/nginx.conf nginx
19eeda1700ee6815e1b4b92a8dc0ba7ffbf6c9085fdb8a18f0ce9404ee97bf3d
[root@localhost nginx]# dps
CONTAINER ID IMAGE PORTS STATUS NAMES
19eeda1700ee nginx 80/tcp, 0.0.0.0:18080-18081->18080-18081/tcp, :::18080-18081->18080-18081/tcp Up 1 second nginx
25761d94c3db mysql 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp Up 28 minutes mysql
e5c900979c64 hmall 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp Up 56 minutes hmall
[root@localhost nginx]#
nginx配置文件:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/json;
sendfile on;
keepalive_timeout 65;
server {
listen 18080;
# 指定前端项目所在的位置
location / {
root /usr/share/nginx/html/hmall-portal;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass http://hmall:8080;
}
}
server {
listen 18081;
# 指定前端项目所在的位置
location / {
root /usr/share/nginx/html/hmall-admin;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /api {
rewrite /api/(.*) /$1 break;
proxy_pass http://hmall:8080;
}
}
}
8.4 测试访问
大功告成🎉。
九、DockerCompose
Docker Compose通过一个单独的docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器,帮助我们实现多个相互关联的Docker容器的快速部署。
docker run和DockerCompose具有一定的对应关系。
docker compose的命令格式如下:
docker compose [OPTIONS] [COMMAND]
| 类型 | 参数或指令 | 说明 |
|---|---|---|
| Options | -f | 指定compose文件的路径和名称 |
| Options | -p | 指定project名称 |
| Commands | up | 创建并启动所有service容器 |
| Commands | down | 停止并移除所有容器、网络 |
| Commands | ps | 列出所有启动的容器 |
| Commands | logs | 查看指定容器的日志 |
| Commands | stop | 停止容器 |
| Commands | start | 启动容器 |
| Commands | restart | 重启容器 |
| Commands | top | 查看运行的进程 |
| Commands | exec | 在指定的运行中容器中执行命令 |
通过dockerCompose部署应用的yml文件:docker-compose.yml
version: "3.8"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
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
hmall:
build:
context: .
dockerfile: Dockerfile
container_name: hmall
ports:
- "8080:8080"
networks:
- hm-net
depends_on:
- mysql
nginx:
image: nginx
container_name: nginx
ports:
- "18080:18080"
- "18081:18081"
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
- "./nginx/html:/usr/share/nginx/html"
depends_on:
- hmall
networks:
- hm-net
networks:
hm-net:
name: hmall
重点关注各类路径问题。
Docker Compose 文件中的
version字段用于指定使用的 Compose 文件格式版本。这个字段对于确保你的 Compose 文件能够被 Docker Compose 正确解析非常重要,因为不同版本的 Compose 支持不同的语法和特性。
将之前的容器/镜像全都删除之后,创建一个新的目录,目录内容:
还需要注意一下Dockerfile中构建的镜像是之前idea打好的jar包——hm-service.jar。
docker compose -p heimamall up -d
dps查看容器:
访问测试:
docker compose一键部署成功。
删除项目:
docker compose -p heimamall down
参考
https://b11et3un53m.feishu.cn/wiki/Rfocw7ctXij2RBkShcucLZbrn2d


















