Docker基础

文章目录

1. 什么是 Docker

Docker 的概念

Docker 是一个开源的应用容器引擎,简单来说,它就像是一个"打包工具"。它可以把你的应用程序和它所需要的所有东西(如库、依赖、配置等)都打包在一起,放到一个叫做"容器"的东西里面。这个容器就像是一个小盒子,你可以把它搬到任何一台装有 Docker 的机器上运行,无论是你的电脑、服务器,还是云平台。

这样做的好处是,你不需要担心在不同的机器上运行你的应用会出现环境配置不一致的问题。因为容器里面已经包含了应用运行所需的一切,保证了在任何地方都能以同样的方式运行。

Docker 的特点

  • 轻量级:Docker 容器利用宿主机的操作系统内核,不需要额外安装一个完整的操作系统(不像虚拟机那样)。因此,容器的启动速度非常快,占用的资源也很少,就像运行一个普通的进程一样。
  • 高效性:通过 Docker 镜像(应用和环境的打包文件),可以非常快速地部署和启动应用程序,节省了时间和系统资源。
  • 可移植性:Docker 镜像可以在任何安装了 Docker 的平台上运行,无论是 Windows、Linux 还是 Mac。这意味着开发者可以"构建一次,随处运行",确保应用在不同环境下的行为一致。
  • 灵活性:Docker 支持将应用程序拆分为多个小的服务(微服务架构),每个服务都运行在自己的容器中。这样,开发、部署和扩展应用程序就更加方便和灵活。
  • 隔离性:每个容器都是独立的,彼此之间不会互相影响。这就像每个应用都有自己的"独立空间",提高了安全性和稳定性。

2. Docker 的应用场景

Docker 在软件开发和运维中有着广泛的应用。

  1. 持续集成/持续部署(CI/CD)
    • 问题:在软件开发过程中,开发人员需要频繁地编写代码、测试和部署。每次部署都可能需要手动配置环境,费时费力,而且容易出错。
    • Docker 的作用:使用 Docker,可以将应用程序和它的运行环境一起打包成一个容器。这样,无论是在开发、测试还是生产环境,运行的都是同一个容器,确保了一致性。部署新版本时,只需替换容器即可,大大提高了交付效率。
  2. 微服务架构
    • 问题:将一个大型应用拆分成多个小服务(微服务)后,每个服务可能使用不同的技术栈(比如不同的编程语言、数据库等),管理和部署变得复杂。
    • Docker 的作用:Docker 可以为每个微服务创建独立的容器,里面包含该服务所需的一切。这样,每个服务都可以独立开发、测试和部署,互不干扰,方便升级和扩展。
  3. 环境隔离
    • 问题:开发、测试、生产环境可能有不同的配置和依赖,导致应用在不同环境中运行出现问题,比如"在我的电脑上能跑,怎么上线就出错了?"。
    • Docker 的作用:通过将应用和其依赖环境一起打包到容器中,确保在任何环境下运行的都是相同的容器,避免了环境差异带来的问题。
  4. 资源优化
    • 问题:传统的虚拟机需要运行完整的操作系统,占用大量资源,启动也很慢,导致服务器的资源利用率不高。
    • Docker 的作用:Docker 容器非常轻量级,启动快,占用资源少。这样,在同一台服务器上可以运行更多的容器,提高硬件资源的利用率,节省成本。
  5. 快速交付和部署
    • 问题:部署应用可能涉及复杂的安装和配置过程,需要安装依赖、设置环境等,费时费力。
    • Docker 的作用:Docker 镜像包含了应用运行所需的一切,部署时只需拉取镜像并运行容器即可。这样,可以快速地将应用部署到服务器上,实现快速迭代和交付。
  6. 跨平台部署
    • 问题:应用需要在不同的操作系统或环境中运行,可能会遇到兼容性问题,需要针对不同平台进行适配。
    • Docker 的作用:Docker 镜像可以在任何安装了 Docker 的平台上运行,无论是 Linux、Windows 还是 MacOS。这样,我们只需构建一次镜像,就可以在不同的平台上部署,解决了跨平台兼容性的问题。
  7. 简化配置
    • 问题:手动配置应用的运行环境可能复杂且容易出错,需要安装各种依赖、设置环境变量等。
    • Docker 的作用:将应用运行所需的所有环境和配置都写入 Dockerfile,构建镜像时自动配置好。这样,部署时不需要再手动配置环境,避免了出错的可能。

3. Docker 常用命令

详细命令参考官网

docker pull

  • 作用:从镜像仓库中拉取镜像。
  • 示例 : 从镜像仓库中拉取 nginx 镜像。
bash 复制代码
docker pull nginx

docker push

  • 作用:将本地镜像上传到镜像仓库。
  • 示例 : 将名为 your-repo/your-image(自己镜像的名字) 的本地镜像推送到镜像仓库。
bash 复制代码
docker push your-repo/your-image

docker images

  • 作用:列出本地所有的镜像。
  • 示例: 查看本地所有的 Docker 镜像。
bash 复制代码
docker images

docker run

  • 作用:创建并运行容器。
  • 示例 : 使用 nginx 镜像,在后台运行一个名为 nginx 的容器,将宿主机的 80 端口映射到容器的 80 端口。
bash 复制代码
docker run -d --name nginx -p 80:80 nginx
  • 参数说明
    • -d:后台运行容器(detached 模式)。
    • --name nginx:为容器指定名称为 nginx
    • -p 80:80:将宿主机的 80 端口映射到容器的 80 端口。

docker ps

  • 作用:查看运行中的容器。
  • 示例: 列出当前正在运行的 Docker 容器。
bash 复制代码
docker ps
  • 格式化输出 :为了使输出信息更清晰,可以使用 --format 参数:
bash 复制代码
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"

docker stop

  • 作用:停止容器。
  • 示例 : 停止名为 nginx 的容器。
bash 复制代码
docker stop nginx

docker start

  • 作用:启动已停止的容器。
  • 示例 : 启动名为 nginx 的容器。
bash 复制代码
docker start nginx

docker inspect

  • 作用:查看容器的详细信息。
  • 示例 : 查看名为 nginx 的容器的详细信息。
bash 复制代码
docker inspect nginx

docker exec

  • 作用:在运行中的容器内执行命令。
  • 示例 1 :进入名为 nginx 的容器的交互式终端。
bash 复制代码
docker exec -it nginx bash
  • 示例 2 :在名为 mysql 的容器内,以 root 用户连接 MySQL 数据库。
bash 复制代码
docker exec -it mysql mysql -uroot -p

docker rm

  • 作用:删除容器。
  • 示例 1 : 删除名为 nginx 的已停止的容器。
bash 复制代码
docker rm nginx
  • 示例 2 : 强制删除名为 nginx 的正在运行的容器。
bash 复制代码
docker rm -f nginx

docker logs

  • 作用:查看容器的日志。
  • 示例 : 实时查看名为 nginx 的容器的日志。
bash 复制代码
docker logs -f nginx

4. 配置命令别名

为了提高操作效率,可以为常用的 Docker 命令配置别名。

步骤一:编辑 .bashrc 文件

  • 使用以下命令打开 .bashrc 文件:
bash 复制代码
vi ~/.bashrc

步骤二:添加别名配置

  • 在文件中添加以下内容:
bash 复制代码
# 自定义命令别名

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
alias dis='docker images'

步骤三:使配置生效

  • 保存并退出编辑器后,执行以下命令:
bash 复制代码
source ~/.bashrc

现在,就可以使用简化的命令,如 dps 来替代 docker ps


5. 数据卷(Volumes)

什么是数据卷?

数据卷是 Docker 中用于持久化和共享数据的机制。通过数据卷,可以将宿主机的目录映射到容器内的目录,实现数据的持久化和共享。

如何挂载数据卷?

在创建容器时,使用 -v 参数指定数据卷的名称和挂载点。

示例

bash 复制代码
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx

说明

  • -v html:/usr/share/nginx/html:将名为 html 的数据卷挂载到容器内的 /usr/share/nginx/html 目录。
  • 如果指定的数据卷不存在,Docker 会自动创建。

数据卷的工作原理

示意图

说明:

  • 创建了数据卷 htmlconf
  • 容器内的目录 /usr/share/nginx/html 与数据卷 html 关联,/etc/nginx/conf与数据卷 conf关联。
  • 数据卷 html 对应宿主机的目录 /var/lib/docker/volumes/html/_data,数据卷 conf 对应宿主机的目录 /var/lib/docker/conf/_data,这样一来,容器内的 conf 和 html 目录就与宿主机的 conf 和 html 目录关联起来,称为挂载
  • 操作宿主机的/var/lib/docker/volumes/html/_data目录,相当于在操作容器内的 /usr/share/nginx/html,操作宿主机的/var/lib/docker/conf/_data目录,相当于在操作容器内的 /etc/nginx/conf,只要将静态资源放入宿主机对应目录,就可以被 nginx 代理了。

数据卷常用命令

  • 查看数据卷
bash 复制代码
docker volume ls
  • 删除数据卷
bash 复制代码
docker volume rm [数据卷名称]
  • 查看数据卷详情
bash 复制代码
docker volume inspect [数据卷名称]
  • 删除未使用的数据卷
bash 复制代码
docker volume prune

6. 本地目录挂载

除了使用数据卷名,还可以直接将宿主机的本地目录挂载到容器内。

示例:运行 MySQL 容器,并将本地目录挂载到容器内。

bash 复制代码
docker run -d \
  --name mysql \
  -p 3306:3306 \
  -e TZ=Asia/Shanghai \
  -e MYSQL_ROOT_PASSWORD=123 \
  -v $(pwd)/mysql/data:/var/lib/mysql \
  -v $(pwd)/mysql/conf:/etc/mysql/conf.d \
  -v $(pwd)/mysql/init:/docker-entrypoint-initdb.d \
  mysql

说明

  • 在上述命令中,需要确保当前目录下存在 mysql/datamysql/confmysql/init 这三个目录,否则需要先创建它们。
  • $(pwd) 在命令中用于获取当前目录的路径,方便将当前目录下的文件或目录挂载到容器内, 假设当前的工作目录是 /home/user/project,那么执行 $(pwd) 就会返回 /home/user/project
  • -v $(pwd)/mysql/data:/var/lib/mysql:将当前目录下的 mysql/data 挂载到容器的 /var/lib/mysql,用于数据持久化。
  • -v $(pwd)/mysql/conf:/etc/mysql/conf.d:挂载自定义的 MySQL 配置文件。
  • -v $(pwd)/mysql/init:/docker-entrypoint-initdb.d:挂载初始化脚本。

7. Dockerfile 语法

Dockerfile 是用于构建自定义镜像的脚本文件,包含了一系列指令,定义了镜像的构建过程。

示例 Dockerfile

dockerfile 复制代码
# 基础镜像
FROM openjdk:11-jre-slim

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 创建应用目录
WORKDIR /app

# 拷贝应用程序
COPY docker-demo.jar /app/app.jar

# 暴露端口
EXPOSE 8080

# 启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

常用指令说明

  • FROM:指定基础镜像。
dockerfile 复制代码
FROM centos:7
  • ENV:设置环境变量。
dockerfile 复制代码
ENV TZ=Asia/Shanghai
  • COPY:将文件复制到镜像内。
dockerfile 复制代码
COPY ./app.jar /app/app.jar
  • RUN:在镜像构建时运行的命令。
dockerfile 复制代码
RUN yum install -y wget
  • EXPOSE:声明容器监听的端口(仅作说明,不做端口映射)。
dockerfile 复制代码
EXPOSE 8080
  • ENTRYPOINT:指定容器启动时运行的命令。
dockerfile 复制代码
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

8. 构建自定义镜像

步骤一:准备工作

  • 编写 Dockerfile,示例:
dockerfile 复制代码
# 基础镜像
FROM openjdk:11-jre-slim

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 创建应用目录
WORKDIR /app

# 拷贝应用程序
COPY docker-demo.jar /app/app.jar

# 暴露端口
EXPOSE 8080

# 启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
  • 将应用程序打包,将应用程序的 jar 包(如 docker-demo.jar)和 Dockerfile 放在虚拟机的同一目录下(如 /root/demo)。

步骤二:构建镜像

bash 复制代码
# 进入镜像目录
cd /root/demo

# 开始构建
docker build -t docker-demo:1.0 .

说明

  • -t docker-demo:1.0:指定镜像名称和标签,格式为 repository:tag,不指定 tag 时,默认为 latest
  • .:指定 Dockerfile 所在目录,如果就在当前目录,就指定为"."。

9. 容器网络互联

加入自定义网络的容器才可以通过荣启铭互相访问,Docker 的网络操作命令如下:

创建自定义网络

bash 复制代码
docker network create [网络名 例如:mynetwork]

将容器加入网络

  • 将正在运行的容器加入网络
bash 复制代码
docker network connect mynetwork mysql --alias db
  • 说明
    • mysql:容器名称。
    • --alias db:在网络中为该容器指定别名 db
  • 在启动容器时指定网络
bash 复制代码
docker run -d --name app --network=mynetwork myapp

验证网络连接

  • 进入容器内部
bash 复制代码
docker exec -it app bash
  • 测试网络连接
bash 复制代码
ping db

如果能成功 ping 通,说明容器之间的网络互联成功。

示例:

bash 复制代码
# 1.首先通过命令创建一个网络
docker network create hmall

# 2.然后查看网络
docker network ls
# 结果:
# NETWORK ID     NAME      DRIVER    SCOPE
# 639bc44d0a87   bridge    bridge    local
# 403f16ec62a2   hmall     bridge    local
# 0dc0f72a0fbb   host      host      local
# cd8d3e8df47b   none      null      local
# 其中,除了hmall以外,其它都是默认的网络

# 3.让dd和mysql都加入该网络,注意,在加入网络时可以通过--alias给容器起别名
# 这样该网络内的其它容器可以用别名互相访问!

# 3.1.mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名
docker network connect hmall mysql --alias db

# 3.2.db容器,也就是我们的java项目
docker network connect hmall dd

# 4.进入dd容器,尝试利用别名访问db
# 4.1.进入容器
docker exec -it dd bash

# 4.2.用db别名访问
ping db
# 结果
# PING db (172.18.0.2) 56(84) bytes of data.
# 64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.070 ms
# 64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.056 ms

# 4.3.用容器名访问
ping mysql
# 结果:
# PING mysql (172.18.0.2) 56(84) bytes of data.
# 64 bytes from mysql.hmall (172.18.0.2): icmp_seq=1 ttl=64 time=0.044 ms
# 64 bytes from mysql.hmall (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms

总结

  • 在自定义网络中,容器可以通过容器名或别名相互通信。
  • 使用 --alias 可以为容器指定别名,方便网络内的容器互相访问。

10. 为容器添加网络(启动/运行中)

将正在运行的容器添加到网络

bash 复制代码
docker network connect [网络名] [容器名]

示例

bash 复制代码
docker network connect mynetwork mysql

在容器启动时指定网络

bash 复制代码
docker run --network=[网络名] [其他参数]

示例

bash 复制代码
docker run --network=mynetwork -d --name app myapp
相关推荐
MonkeyKing_sunyuhua1 小时前
ubuntu22.04 docker-compose安装postgresql数据库
数据库·docker·postgresql
追风林2 小时前
mac m1 docker本地部署canal 监听mysql的binglog日志
java·docker·mac
€☞扫地僧☜€3 小时前
docker 拉取MySQL8.0镜像以及安装
运维·数据库·docker·容器
茶馆大橘3 小时前
微服务系列六:分布式事务与seata
分布式·docker·微服务·nacos·seata·springcloud
全能全知者4 小时前
docker快速安装与配置mongoDB
mongodb·docker·容器
阿尔帕兹6 小时前
构建 HTTP 服务端与 Docker 镜像:从开发到测试
网络协议·http·docker
ZHOU西口7 小时前
微服务实战系列之玩转Docker(十八)
分布式·docker·云原生·架构·数据安全·etcd·rbac
景天科技苑10 小时前
【云原生开发】K8S多集群资源管理平台架构设计
云原生·容器·kubernetes·k8s·云原生开发·k8s管理系统
wclass-zhengge11 小时前
K8S篇(基本介绍)
云原生·容器·kubernetes
颜淡慕潇11 小时前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决