Docker常用命令
Docker简介
什么是Docker?
Docker–> “码头工人”;Docker基于go语言开发,遵循apache2.0协议(开源协议,允许软件的商业使用)。
Docker 是一个开源的容器化平台,用于打包、分发和运行应用程序,使得应用程序和它的所有依赖(依赖库、配置文件、环境等)可以被打包成一个轻量级、可移植的容器,这样就能确保应用程序在任何环境中都能一致地运行,而不受操作系统和硬件的限制。Docker的宗旨是“一次封装,到处运行”。
容器(container)使用沙盒机制,容器之间不会存在任何接口。几乎没有性能开销,可以很容易的在计算机和数据中心运行。最重要的是,他们不依赖于任何语言、框架或者系统。
Docker有什么特性?
- 环境隔离: 使用 Docker,可以为每个项目或服务创建独立的容器,这些容器在相同的物理机器上运行时不会相互干扰。使得不同的应用程序、服务可以在完全隔离的环境中运行,避免环境冲突(如同时安装python3.8和python3.9,或者相同服务的不同版本)。
- 微服务架构: Docker 是微服务架构的理想选择,因为每个微服务可以运行在独立的容器中,容器间可以通过网络进行通信。Docker 使得微服务的部署、扩展和管理变得更加容易。
- 持续集成和持续部署(CI/CD): Docker 可以帮助开发人员创建一致的开发和测试环境,避免了传统开发过程中“在A电脑上能运行,在B电脑上无法运行”的问题。同时,Docker 容器可以在不同环境之间快速迁移,简化了持续集成和持续部署的流程。
- 跨平台开发: Docker 容器不依赖于具体的操作系统或硬件环境,因此开发者可以将容器打包并在任何平台(如开发环境、测试环境、生产环境)上运行,保证应用程序的跨平台兼容性。
- 轻量化和资源节省: 相比虚拟机,Docker 容器的开销更小,因为容器与宿主操作系统共享内核,没有冗余的操作系统开销。多个容器可以在同一台机器上高效地共享资源,提升资源利用率。
Docker在不同操作系统上的表现(Linux为主)
- Linux: Docker 最初是基于 Linux 容器技术(LXC)开发的,在 Linux 上运行 Docker 时,容器直接使用 Linux 内核(不同的Linux操作系统共享 Linux 内核的基本功能和特点,如进程管理、内存管理、硬件支持等)提供的技术(如 namespaces 和 cgroups)来实现隔离。因此,Docker 在 Linux 环境下是原生运行的,能够利用系统的资源和特性来提供高效的容器化服务。
- Windows: 在 Windows 上,Docker 本身不能直接利用 Windows 内核的容器功能,因为 Windows 的容器与 Linux 容器是不同的。为了支持在 Windows 上运行 Docker,Docker 使用了 WSL (Windows Subsystem for Linux) 来模拟一个 Linux 环境,让 Docker 能在这个虚拟环境中运行 Linux 容器。因此,尽管 Docker 在 Windows 上能运行,但它仍然依赖于 WSL 提供的虚拟化层,来模拟一个 Linux 环境。
- macOS: 在 macOS 上,Docker 的运行方式类似于 Windows,通过一个虚拟化层来提供 Linux 环境。由于 macOS 本身不支持 Linux 容器,Docker 会在后台启动一个轻量级的虚拟机,通常使用 HyperKit 和 LinuxKit 来实现对 Linux 内核的模拟,允许 Docker 容器在 macOS 上运行。这个虚拟机提供了一个 Linux 环境,容器在其中运行。因此,虽然 Docker 能在 macOS 上运行,但本质上它是在一个虚拟化的 Linux 环境中运行。
Docker 使用 Linux 内核的特性(如 cgroups 和 namespaces)来实现容器化,提供隔离和资源管理:
Namespaces:用于为每个容器提供独立的网络、进程、文件系统等环境,从而实现容器之间的隔离。
**Control Groups (cgroups)**:用于限制、记录和隔离容器使用的资源,如 CPU、内存和磁盘 I/O,确保容器的资源使用不会影响到主机或其他容器。
总结: Docker 是基于 Linux 的技术,虽然它可以在多种操作系统上运行,但其核心功能是建立在 Linux 上的。
容器间通信
通过 Docker 网络进行通信(最常见)
Docker 提供了强大的网络功能来让容器之间能够互相通信。容器可以在同一个网络上进行通信。Docker 默认提供了多种不同的网络模式,可以根据需求选择合适的网络模式。默认网卡是docker0。
a. 桥接网络(Bridge Network)
- 这是 Docker 默认的网络模式。每个容器都连接到一个虚拟的桥接网络(获取一个独立的IP地址),容器可以通过IP地址进行通信,适用于单主机上多容器之间通信。
- 例如 WordPress 和 MySQL 容器都在同一个桥接网络中,它们可以通过容器的 IP 地址或容器名来互相访问。
b. 主机网络(Host Network)
- 主机网络模式让容器共享宿主机的网络接口。容器会直接使用宿主机的 IP 地址进行通信,这意味着容器不再有独立的 IP 地址。容器间通过
localhost或主机 IP 通信。
1 | # 使用主机网络运行容器 |
c. 无网络(None Network)
- 容器不连接任何网络,适用于容器不需要网络通信的情况。
d. 自定义网络(Custom Network)
- 可以为容器创建一个自定义的网络。在自定义网络中,所有的容器都可以通过容器名进行通信(DNS 解析),而不需要知道容器的 IP 地址。
- 例如,可以创建一个名为
wordpress-network的自定义网络,将 WordPress 和 MySQL 容器都连接到这个网络中。然后,WordPress 可以通过mysql来连接 MySQL。
通过共享存储通信
容器也可以通过共享卷(Volume)或绑定挂载(Bind Mount)共享数据。适用于需要共享文件或数据的场景。
共享卷(Volume)
- 特点:
- 数据持久化,独立于容器生命周期。
- 多个容器可以挂载同一个卷。
绑定挂载(Bind Mount)
- 特点:
- 将主机目录挂载到容器中。
- 多个容器可以挂载同一个主机目录。
- 使用场景:
适用于开发环境或需要与主机共享数据的场景。
通过 Docker Compose 简化通信
Docker Compose 是一个用于定义和运行多容器 Docker 应用的工具,支持定义网络、卷和环境变量。通过 docker-compose.yml 文件,可以方便地定义多个服务并让它们在同一网络下进行通信。在 Compose 中定义的服务名实际上就是容器名,可以直接通过服务名进行访问。
例如,WORDPRESS_DB_HOST: mysql:3306 中的 mysql 就是 MySQL 服务的名称。Compose 会自动将这个服务解析为相应的容器。
端口映射(Port Mapping)
当容器需要从外部访问时,Docker 允许将容器的端口映射到宿主机的端口。通常用于容器之间的外部通信,但对于容器内部通信,不需要进行端口映射。我现在使用的openwrt系统内安装的docker容器就是通过这种方式进行访问的。
示例:
-p 3000:8080: 这个用于端口映射(port mapping)。将宿主机的 3000 端口映射到Docker 容器内部的 8080 端口。当访问宿主机的 3000 端口时,Docker 会将这个请求转发到运行在容器内部监听 8080 端口的应用程序。
docker配置端口注意事项
在使用docker run -p 3000:3000创建容器时,一定要注意容器内部使用的端口号(一般官方会给出),如果在运行镜像时将端口映射写成 -p 3000:false port,很可能会导致无法通过宿主机的 3000 端口访问到容器(或者容器提供的web页面)。例如Open WebUI 应用程序在 Docker 容器内部监听的是 8080 端口(这是其默认配置)。端口映射 -p 3000:3000 则是将宿主机的 3000 端口映射到容器内部的3000 端口,导致端口不匹配,由于 Open WebUI 内部的 Web 服务监听的是 8080 端口,而宿主机的 3000 端口映射到了容器内部的3000端口,Docker 就无法正确地将外部对宿主机 3000 端口的访问转发到 Open WebUI 的 Web 服务上(配置云服务器openwebUI时遇到的问题,一个傻逼教程给的命令)。
一个镜像创建成容器时,镜像使用的端口是固定的(容器端口是镜像开发者预先配置好的,应用程序在容器内部监听这些端口),不能随便更改,宿主机端口在运行容器时通过 -p 选项指定,用于将外部流量导向容器内部的相应端口。可以根据需要自由选择宿主机端口(只要不冲突),但要确保它映射到容器内部应用程序实际监听的端口(别填错内部端口)。
1 | # 错误命令,映射了错误的端口 |
docker与虚拟机的区别
| 特性 | Docker | 虚拟机 (VM) |
|---|---|---|
| 资源占用 | 轻量级,资源消耗较少,多个容器共享操作系统内核 | 重,每个独立的操作系统需要更多的资源 |
| 启动速度 | 秒级 | 分钟级 |
| 操作系统 | 共享宿主机操作系统的内核 | 每个虚拟机都有自己的完整操作系统 |
| 资源隔离 | 容器之间共享宿主机内核,但相互隔离 | 完全隔离,每个虚拟机运行独立的操作系统 |
| 性能开销 | 低,几乎没有虚拟化开销 | 高,虚拟化带来额外的性能损失 |
| 计算能力损耗 | 几乎无 | 损耗 50%左右 |
| 迁移 | 容器可以非常容易地在不同主机间迁移 | 迁移虚拟机较复杂,涉及整个操作系统的复制 |
| 硬件虚拟化支持 | 不需要硬件虚拟化支持 | 需要硬件虚拟化支持(如 Intel VT-x 或 AMD-V) |
| 可移植性 | 高,容器化应用能在不同的环境中轻松运行 | 较低,虚拟机需要匹配目标环境的硬件和OS |
| 文件系统 | 容器通过共享宿主机文件系统来运行应用 | 每个虚拟机有自己的独立文件系统 |
| 操作系统兼容性 | 只能运行与宿主机操作系统内核兼容的操作系统 | 可以运行不同操作系统(Windows、Linux、macOS等) |
| 存储 | 通常使用卷(Volumes)与宿主机共享数据 | 虚拟机有自己的虚拟硬盘 |
| 应用部署 | 适用于微服务架构,可以快速部署和扩展 | 适用于运行完整的操作系统和应用,适合更大规模的应用 |
| 隔离性 | 进程隔离 | 系统隔离 |
docker运行流程
docker相关概念
1. 镜像(Image)
Docker将应用程序及其所需的依赖、函数库、环境、配置等文件打包在一起,里面包含了要部署的应用程序以及它所关联的所有库,称为镜像(类似手机.apk安装包 )。镜像是一个只读的模板 ,包含了运行应用程序所需的所有依赖项(代码、运行环境、库等)。类似于虚拟机的快照,容器是基于镜像启动的。镜像中的应用程序运行后形成的进程就是容器。
Docker会给容器进程做隔离。一个镜像可以启动多个容器,多个容器之间互不相关,但都基于一个镜像模版。
Docker 镜像中应该包含应用运行所需的所有内容
运行环境(如 Python、Node.js、Ubuntu、Redis等)
源代码(Flask、Vue.js 项目等)
依赖(
pip install或npm install安装的库)配置文件(环境变量、数据库连接)
容器启动后的执行命令(
CMD或ENTRYPOINT)当项目包含多个组件时(如:Vue + Flask + MySQL + Redis)应使用多个 Dockerfile,并用
docker-compose.yml统一管理。
2. 容器(Container)
容器是镜像的运行实例,本质上是一个轻量级的隔离进程,可以在宿主机上运行,具有自己的文件系统、进程空间和网络环境。容器可以被创建、启动、停止、删除,每个容器之间默认是相互隔离的。
3. 仓库(Repository)
仓库是一个存储和分享 Docker 镜像的地方。Docker Hub 是官方提供的公共仓库,用户可以将自己的镜像推送到仓库中,也可以从仓库中拉取镜像。官方仓库是所有人都可以访问和使用的仓库。还有其他源站等。国内也有类似DockerHub的镜像托管平台,像网易云镜像服务、阿里云镜像服务、私有云(公司自建)等。
Dockerfile和Docker Compose有什么区别?
在实际应用中Docker Compose是非常非常重要的!!!可以通过一个简单的compose.yaml文件方便地管理多个容器及它们的依赖关系,做到一键启动服务。
Dockerfile 是一个文本文件,类似一个自动化脚本,用于构建 Docker 镜像,类似于在虚拟机中安装操作系统和软件。包含一系列指令和步骤,这些步骤指导 Docker 从基础镜像开始,如何一步一步安装软件、复制文件、配置环境等,最终构建出一个用户自定义的镜像。
常见的 Dockerfile 指令:
FROM: 指定基础镜像(必须是 Dockerfile 的第一条指令)LABEL:添加元数据(如维护者信息)RUN: 执行命令(如pip安装软件包), RUN允许在创建镜像时运行任意的 shelI命令,如ls、cat、pwd等COPY: 将文件从宿主机复制到镜像ADD: 添加文件和目录,并支持从 URL 下载WORKDIR:用于设置工作目录,指定了接下来所有的命令(如RUN、CMD、ENTRYPOINT、COPY和ADD)都将在该目录下执行。如果指定的目录不存在,WORKDIR会自动创建该目录。CMD: 设置容器启动时执行的默认命令EXPOSE: 声明容器监听的端口ENV: 设置环境变量
dockerfile示例
1 | # 使用官方的 Python 3.9 作为基础镜像 |
Docker Compose 是一个定义和管理多容器应用的工具,通过 docker-compose.yml 文件来定义多个容器之间的关系、网络、卷挂载等信息,能够通过一个命令启动一个多容器应用。Docker Compose 主要用来协调和管理多个服务的生命周期,而不仅仅是构建一个镜像。
Docker会为每一个compose文件都自动创建一个子网,同一个compose文件里面定义的所有容器都会自动加入同一个子网,这个子网内的所有容器都能相互通信;Docker Compose可以通过depends_on(依赖于哪一个容器,先把它启动)参数自定义容器的启动顺序。
Docker Compose 适用场景
- 管理多个容器:如
Flask + PostgreSQL + Redis组合。 - 简化本地开发:开发环境可一键启动、停止,而不需要手动执行
docker run。 - 配置管理:所有容器配置集中管理,环境变量、端口映射、数据卷等一目了然。
Docker Compose示例:
在 docker-compose.yml 文件中,build 和 image 用于定义容器如何获取镜像,它们的使用方式有所不同。build: 用于构建自定义镜像,通常和 Dockerfile 搭配使用,需要提供 Dockerfile 所在目录,Docker Compose 会自动执行 docker build 生成镜像。image: 用于直接拉取现成的镜像(通常来自 Docker Hub 或私有仓库)。适用于使用官方镜像或已有的镜像,而不需要自己构建Dockerfile。
1 | # 目录结构 |
使用dockerfile的docker run 只启动一个单独的容器,通常需要手动指定镜像、端口、环境变量等;docker-compose up 可以同时启动多个容器,并且自动管理它们的依赖关系(如 Web 服务依赖数据库),所有服务都在 docker-compose.yml 文件中定义,不需要手动运行多个 docker run 命令。
Docker常用命令
常用参数:
-d:后台运行-it:交互模式,让用户可以与容器内的进程交互,比如运行bash进入容器并执行命令--name:给容器指定名称-p 主机端口:容器端口:映射端口-v 宿主机目录:容器目录:挂载目录- /bin/bash:
/bin/bash是进入 Ubuntu 镜像中的 Shell 解释器,允许用户在容器内执行命令。
版本与帮助命令
| 命令 | 作用 |
|---|---|
docker -v |
查看docker版本 |
docker version |
查看详细的 Docker 版本信息 |
docker info |
查看 Docker 运行状态、存储驱动等信息 |
docker help |
显示 Docker 帮助信息 |
docker <command> --help |
查看某个具体命令的帮助 |
镜像管理
| 命令 | 作用 |
|---|---|
docker images |
查看本地镜像 |
docker build -t <镜像名>:<标签> . |
根据 Dockerfile 构建 Docker 镜像,”.”表示根据当前目录作为构建上下文 |
docker search <镜像名> |
在 Docker Hub 搜索镜像 |
docker pull <镜像名>:<标签> |
下载镜像(默认 latest) |
docker rmi <镜像ID> |
删除本地镜像 |
docker tag <本地镜像ID> <仓库名>:<标签> |
给本地镜像打标签 |
| docker push <仓库名>:<标签> | 上传镜像到 Docker Hub |
docker history <镜像名> |
查看镜像的构建历史 |
docker inspect <镜像名> |
查看镜像详细信息 |
容器管理
| 命令 | 作用 |
|---|---|
docker ps |
查看运行中的容器 |
docker ps -a |
查看所有容器(包括已停止) |
docker run <镜像名> |
运行一个容器 |
docker run -d <镜像名> |
后台运行容器 |
docker run -it <镜像名> /bin/bash |
以交互模式运行容器 |
docker start <容器ID> |
启动已停止的容器 |
docker stop <容器ID> |
停止容器 |
docker restart <容器ID> |
重启容器 |
docker rm <容器ID> |
删除容器 |
docker logs <容器ID> |
查看容器日志 |
docker inspect <容器ID> |
查看容器详细信息 |
docker top <容器ID> |
查看容器内运行的进程 |
docker stats <容器ID> |
查看容器资源占用情况 |
docker commit <容器ID> <新镜像名> |
将容器保存为新镜像 |
1 | # 示例 |
进入容器
| 命令 | 作用 |
|---|---|
docker exec -it <容器ID> /bin/bash |
进入正在运行的容器 |
docker attach <容器ID> |
连接到容器的终端 |
docker cp <容器ID>:<容器内路径> <宿主机路径> |
从容器拷贝文件到宿主机 |
docker cp <宿主机路径> <容器ID>:<容器内路径> |
从宿主机拷贝文件到容器 |
数据卷(持久化存储)
| 命令 | 作用 |
|---|---|
docker volume ls |
查看所有数据卷 |
docker volume create <卷名> |
创建数据卷 |
docker volume rm <卷名> |
删除数据卷 |
docker volume inspect <卷名> |
查看数据卷详细信息 |
docker run -v <卷名>:<容器路径> <镜像名> |
绑定数据卷到容器 |
网络
| 命令 | 作用 |
|---|---|
docker network ls |
查看所有网络 |
docker network create <网络名> |
创建网络 |
docker network rm <网络名> |
删除网络 |
docker network inspect <网络名> |
查看网络信息 |
docker network connect <网络名> <容器名> |
连接容器到指定网络 |
docker network disconnect <网络名> <容器名> |
断开容器的网络连接 |
docker compose
| 命令 | 作用 |
|---|---|
docker-compose up |
启动所有服务 |
docker-compose up -d |
以后台方式启动 |
docker-compose down |
停止并删除所有容器 |
docker-compose ps |
查看 Compose 管理的容器 |
docker-compose logs |
查看日志 |
docker-compose build |
构建镜像 |
docker-compose restart |
重启服务 |
docker-compose stop |
只停止不删除容器 |
docker-compose start |
把stop命令停止的容器再重新启动 |
牛角尖
使用
dockerfile构造镜像时,引用的一些基础镜像(如 MySQL、Redis、Python 等)已经包含了它们所依赖的操作系统环境,不需要再单独指定操作系统,基础镜像会提供它们所需要的基础的操作系统。每个基础镜像都已经包含了其需要的操作系统环境和相关的依赖库。比如python:3.9-slim会包含一个精简的操作系统和 Python,mysql:8.0会包含一个操作系统和 MySQL。当选择一个基础镜像时,实际上已经选择了操作系统环境,这样你就不需要手动指定操作系统了。后续操作中即便没有明确指定操作系统,容器内部仍然是有文件系统的(由基础镜像提供),并且可以在这个文件系统中创建和操作目录。WORKDIR是用来设置在容器内的文件操作目录的。使用
COPY将文件从主机复制到镜像工作目录WORKDIR时,COPY . /app表示将宿主机(构建 Docker 镜像的机器)当前目录下的文件(例如app.py、requirements.txt等)复制到容器的/app目录;当用户构建镜像时,COPY指令已经将宿主机上的文件复制到镜像的指定工作目录上了。在构建镜像的过程中,这些文件会成为镜像的一部分。因此,其他人在使用这个镜像时,镜像中已经包含了这些文件,不需要再手动复制。当我构建好一个镜像时,镜像就相当于一个“只读”模板。镜像内部包含了操作系统(如果使用了基础镜像的话)、所有应用、依赖、环境变量以及通过COPY指令复制的文件。容器是镜像的运行实例。当我启动容器时,它会基于镜像创建一个“可写”的文件系统,并执行我在
Dockerfile中指定的命令(如CMD或ENTRYPOINT)。所以容器内部已经包含了所有在镜像构建过程中复制进去的文件。如CMD ["python", "app.py"],当容器启动时,它会在/app目录下执行python app.py。










