Docker三剑客实战指南:Docker、Dockerfile 和 Docker Compose

文章目录

DockerDockerfileDocker Compose 是容器化技术的"三剑客"。

  • Docker :真正的引擎/执行者(负责构建镜像并运行容器)。
  • Dockerfile :容器的蓝图/配方(定义如何构建单个镜像)。
  • Docker Compose :多容器的指挥官/编排工具(定义和运行多个相互协作的容器服务)。

三者之间的流转关系如下:

bash 复制代码
编写 Dockerfile ──> docker build ──> 生成镜像 (Image) ──> docker run ──> 运行容器 (Container)
                                                                 ▲
                                                                 │ (统一管理多个容器)
`docker-compose.yml` 配置文件 ─────────────────────────> docker-compose up

Docker

背景知识

传统软件开发与运维的痛点在于"环境不一致"。一款产品从开发到上线,涉及操作系统、运行环境、依赖版本等多种配置。不同版本迭代后环境兼容性极差,常引发"在我的机器上能运行,在他人机器上不行"的问题。

Docker 提供了一套标准化的解决方案:镜像即应用。它将应用程序及其所有依赖(代码、运行环境、系统库、配置文件等)打包成一个可交付的统一镜像,从而彻底打破开发与运维之间的环境壁垒。

Docker三要素

  • 仓库 (Repository):集中存放镜像文件的场所(分为公开库如 Docker Hub,以及私有库如 Harbor)。
  • 镜像 (Image) :一个只读的模版,相当于面向对象编程中的。用来实例化生成容器。
  • 容器 (Container) :镜像运行时的独立实体,相当于面向对象编程中的对象。容器之间相互隔离,独立运行。

Linux安装部署

shell 复制代码
# 1. 卸载旧版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

# 2. 设置 Docker 阿里云镜像源
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 3. 安装 Docker 引擎及其组件
sudo yum install -y docker-ce docker-ce-cli containerd.io

# 4. 启动 Docker 并设置开机自启
sudo systemctl enable docker --now

# 5. 配置镜像加速器与日志限制
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

常用命令

防火墙命令

shell 复制代码
sudo firewall-cmd --list-all --zone=public                         # 查看防火墙对外提供访问的接口
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent      # 开放TCP端口80(HTTP)
sudo firewall-cmd --zone=public --remove-port=80/tcp --permanent   # 关闭TCP端口80(HTTP
sudo firewall-cmd --permanent --query-port=80/tcp                  # 查看端口是否开启
service firewalld status
service firewalld stop
service firewalld start
service firewalld restart

镜像命令

shell 复制代码
1 帮助命令:
    docker version
    docker info
    docker --help

2 镜像命令:
    1、列出本地镜像:docker images [-options]
        -a:列出本地所有镜像
        -q:只显示镜像ID
        --digests:显示镜像的摘要信息
        --no-trunc:显示完整的镜像信息
        docker images -a
        docker images -q
    2、查询DockerHub镜像:docker search [-options] 镜像名
        docker search tomcat:列出tomcat的镜像
        docker search --no-trunc tomcat:显示完整的镜像描述
    3、下载镜像到本机:docker pull 镜像名
        docker pull tomcat   		下载最新镜像tomcat,等同于docker pull tomcat:latest
        docker pull redis:6.2.4 	下载指定版本镜像
    4、删除本机镜像:docker rmi -f 镜像名/镜像id
        docker rmi [-f] tomcat

容器命令

shell 复制代码
容器命令:有镜像才能实例化容器(提前下载一个centos镜像仅有200MB)
# 1. 前台交互式运行容器
docker run -it --name my-centos centos:7 /bin/bash
        --name:容器的新别名
        -i:以交互方式启动容器,通常与-t同时使用
        -t:为容器分配一个伪输入终端
        -d:以守护进程方式启动容器

# 2. 后台守护进程方式运行容器(端口映射 + 自动重启)
  以交互方式启动容器(为主):前台启动
      docker run --it --name my-centos centos:7 /bin/bash
  以守护进程方式启动容器:运行在后台
      docker run -d --name=mynginx --restart=always -p 88:80 nginx
        
# 3. 查看容器状态
docker ps                           # 查看运行中的容器
docker ps -a                      # 查看所有容器(含已停止的)

# 4. 容器生命周期控制
docker stop <container_id>          # 停止容器
docker start <container_id>         # 启动容器
docker restart <container_id>       # 重重启容器
docker rm -f <container_id>         # 强制删除容器

# 5. 查看日志与容器进程
docker logs -f <container_id>       # 实时查看容器日志
docker top <container_id>          # 查看容器内运行的进程

进阶命令

shell 复制代码
1、进容器内部
    docker exec -it 容器id  /bin/bash  # 在新的容器中打开新的命令终端,可以启动新的进程
2、挂载数据到外部修改
    docker run --name=mynginx \ 
    -d --restart=always \
    -p  88:80 \
    -v /data/html:/usr/share/nginx/html:ro \ # 修改页面只需要去主机的 /data/html
    nginx:latest 
3、镜像分享方案一
    docker save -o mynginx.tar nginx # 将镜像保存成压缩包
    docker load -i abc.tar 			 # 别的机器将压缩包加载为镜像
4、镜像分享方案二【需要docker hub账号】
    docker commit -m "首页变化" 341d81f7504f guignginx:v1.0  # 将自己修改好的镜像提交
    在docker hub 注册仓库
    docker tag guignginx:v1.0 leifengyang/guignginx:v1.0 	# 把旧镜像的名字,改成仓库要求的新版名字
    docker login  							# 登录到docker hub
    docker push leifengyang/guignginx:v1.0  # 推送
    docker logout 							# 推送完成镜像后退出
    docker pull leifengyang/guignginx:v1.0  # 别的机器下载
5、查看容器运行情况
    docker top 容器名称或容器id   # 查看容器内运行的进程
    docker inspect 容器名称或容器id # 查看容器内部细节
    docker attach 容器名称或容器id # 进入正在运行的容器并以命令行交互, 不会启动新的进程
6、从容器内拷贝文件到主机上:		
    docker cp 容器id: 容器路径 目的主机路径

Dockerfile镜像文件

配置文件-Dockerfile

Dockerfile中文名叫镜像描述文件,是一个包含用于组合镜像目录的文本文档,也可以叫"脚本"。他通过读取Dockerfile中的指令安装步骤自动生成镜像。

常用指令说明:

shell 复制代码
# 1. FROM
# 指定基础镜像(如 Python 环境、Node 环境等)
FROM openjdk:8

# 2. MAINTAINER
# 谁创造了它(作者信息)
MAINTAINER zhupeng

# 3. WORKDIR
# 设置容器内部的工作目录,若发现没有这个目录,就自动创建出来
WORKDIR /usr/local/testdir

# 4.COPY
# 文件拷贝:把宿主机(本地)的文件复制到容器内
# 案例一:将1.txt拷贝到根目录下。它不仅仅能拷贝单个文件,还支持Go语言风格的通配符,比如如下:
COPY 1.txt /
# 案例二:拷贝所有 abc 开头的文件到testdir目录下
COPY abc* /testdir/
# 案例三:? 是单个字符的占位符,比如匹配文件 abc1.log
COPY abc?.log /testdir/

# 5.ADD
# 往它肚子里放点文件(会自动解压)
ADD springboot-1.0-SNAPSHOT.jar app.jar
# 案例一:将1.txt拷贝到根目录的abc目录下。若/abc不存在,则会自动创建
ADD 1.txt /abc
# 案例二:将test.tar.gz解压缩然后将解压缩的内容拷贝到/home/work/test
ADD test.tar.gz /home/work/test

# ADD/COPY对比
# 1.二者都是只复制目录中的文件,而不包含目录本身。
# 2.COPY能干的事ADD都能干,甚至还有附加功能。
# 3.ADD可以支持拷贝的时候顺带解压缩文件,以及添加远程文件(不在本宿主机上的文件)
# 4.只是文件拷贝的话可以用COPY,有额外操作可以用ADD代替。


# 6.ENV
# 设置环境常量,方便下文引用
ENV JAVA_HOME /usr/local/jdk1.8
RUN ${JAVA_HOME}/bin/java -jar xxx.jar

# 7.RUN
# 在构建镜像阶段执行命令(如 pip install、apt install)。
# SHELL命令格式:RUN yum -y install vim
# EXEC命令格式:	RUN ["yum","-y","install","vim"]

# 8.CMD:设置容器启动时默认执行的命令
# 1.容器启动时执行,而不是镜像构建时执行[docker run]
# 2.Dockerfile中只有最后一个ENTRYPOINT会被执行,推荐用EXEC格式。
# 3.重点在于如果容器启动的时候有其他额外的附加指令,则CMD指令不生效。
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

# 9.ENTRYPOINT
# 容器创建时执行,而不是镜像构建时执行。
# Dockerfile中只有最后一个ENTRYPOINT会被执行,推荐用EXEC格式。
ENTRYPOINT ["java","-jar","app.jar"]

# 给我一个存放行李的地方(目录挂载):将本地文件夹挂载到当前容器
VOLUME /tmp

# 声明需要暴露的端口
EXPOSE 8080

构建命令

有了 Dockerfile 之后,我们使用 docker 命令行工具来进行构建和运行:

shell 复制代码
# 1. 构建镜像:读取当前目录的 Dockerfile,生成名为 my-fastapi-app 的镜像
docker build -t my-fastapi-app .

# 2. 启动容器:将宿主机的 8000 端口映射到容器的 8000 端口,并在后台运行 (-d)
docker run -d -p 8000:8000 --name my-running-app my-fastapi-app

# 3. 将镜像导出为离线归档文件 (.tar)
docker save -o low-altitude-economy:4.0.0-20260609-1666.tar harbor.nimbus.com/nimbus/low-altitude-economy:4.0.0-20260609-1666

# 4. 从离线归档文件恢复加载镜像
docker load -i harbor.nimbus.com/nimbus/low-altitude-economy:4.0.0-20260609-1666.tar
docker load < harbor.nimbus.com/nimbus/low-altitude-economy:4.0.0-20260609-1666.tar


# 5. 登录私有镜像仓库 (如 Harbor)
docker login -u admin -p Harbor12345 harbor.nimbus.com  // 开发环境
docker login -u admin -p sgk@8Lou harbor.nimbus.com 		// 一般默认密码

# 6. 推送镜像至远程仓库
docker push harbor.nimbus.com/nimbus/low-altitude-economy:4.0.0-20260609-1666

实战案例:Spring Boot 项目镜像构建

添加依赖

xml 复制代码
        <plugins>
            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>1.2.2</version>
                <configuration>
                    <imageName>docker/${project.artifactId}</imageName> <!-- 镜像名称  -->
                    <dockerDirectory>src/main/docker</dockerDirectory>  <!-- Dockerfile文件存放目录:后续改为项目根目录,后续Dockfile文件一定要放在这 -->
                    <resources>
                        <resource>
                            <targetPath>/</targetPath>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
            <!--这个插件,可以将应用打包成一个可执行的jar包-->
                      <!--千万不能丢掉,不然web项目没有main入口-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.5.2</version>
                <configuration>
                    <fork>true</fork>
                </configuration>
            </plugin>
        </plugins>

Dockfile

dockerfile 复制代码
# 基于openjdk 镜像,如果镜像不是本地的会从 DockerHub 进行下载
FROM openjdk:8

# VOLUME 指向了一个/tmp的目录,由于 SpringBoot使用内置的Tomcat容器,Tomcat 默认使用/tmp作为工作目录。
# 这个命令的效果是:在宿主机的/var/lib/docker目录下创建一个临时文件并把它链接到容器中的/tmp目录
VOLUME /tmp

# 作者
MAINTAINER zhupeng

# 将本地JAR包打包到容器中,并重命名
ADD springboot-1.0-SNAPSHOT.jar app.jar

# 声明需要暴露的端口 在Dockerfile中声明了那些端口是需要开放的,在构建容器时通过-p可以随机映射端口,如果EXPOSE没有指定端口,那么使用-p参数无效。本配置只是声明,一般我们需要在构建docker容器时使用-p(小写的p)指定开放的端口。
EXPOSE 8080

# 配置容器启动后执行的命令
ENTRYPOINT ["java","-jar","app.jar"]

执行构建

mvn clean package -Dmaven.test.skip=true docker:build # 前提要有docker环境

PS:如果还win执行mvn指令:mvn clean package '-Dmaven.test.skip=true'

启动镜像

dockerfile 复制代码
 docker images -a
 docker run -d --name my-springboot -p 8080:8080 docker/springboot-multipart [务必指定暴露端口]
 
 docker ps -a
 docker logs -f 976e5ee13513ed3

测试:http://10.1.42.71:8080/test/show

Docker Compose多容器编排

用于一键启动多容器集群为了解决"多容器联动"的问题,就有了 Docker Compose

你只需要编写一个 docker-compose.yml 文件,把所有服务(后端、数据库、缓存等)的配置写在一起,然后用一条命令全部拉起。

配置文件-docker-compose.yml

sql 复制代码
services:
  # 服务 1:FastAPI 后端应用
  app:
    build:
      context: .             # 指定构建上下文为当前目录
      dockerfile: Dockerfile
    ports:
      - "8000:8000"          # 端口映射(宿主机端口 : 容器内部端口)
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/my_db  # 数据库连接(直接通过服务名 db 通信)
      - REDIS_URL=redis://redis:6379/0
    depends_on:
      db:
        condition: service_healthy  # 关键:严格等待数据库健康检查通过后再启动 app
      redis:
        condition: service_started
    networks:
      - app-network

  # 服务 2:PostgreSQL 数据库
  db:
    image: postgres:15-alpine
    restart: unless-stopped  # 容器异常退出时自动重启
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: my_db
    volumes:
      - postgres_data:/var/lib/postgresql/data  # 挂载宿主机数据卷,防止容器销毁导致数据丢失
    healthcheck:             # 健康检查:确保数据库已具备接收连接能力
      test: ["CMD-SHELL", "pg_isready -U user -d my_db"]
      interval: 5s
      timeout: 5s
      retries: 5
    networks:
      - app-network

  # 服务 3:Redis 缓存
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    ports:
      - "6379:6379"
    networks:
      - app-network

# 声明持久化数据卷与独立网络
volumes:
  postgres_data:

networks:
  app-network:
    driver: bridge

构建命令

sql 复制代码
# 1. 一键构建并后台启动所有服务集群
docker compose up -d --build

# 2. 查看当前集群中各服务容器的运行与健康状态
docker compose ps

# 3. 实时追踪查看所有容器(或指定服务)的运行日志
docker compose logs -f

# 4. 仅查看后端应用服务的日志
docker compose logs -f app

# 5. 一键优雅停止并销毁整个容器集群(数据卷 postgres_data 依然保留)
docker compose down

# 6. 【极高危操作】销毁集群并连同挂载的数据卷一并彻底清空
docker compose down -v
相关推荐
0566461 小时前
用大模型构建答疑机器人:从 API 调用到上下文工程
python·学习·agent
haluhalu.1 小时前
初识 Protobuf:微服务跨语言通信的一份契约
java·c语言·开发语言·c++·python
Liaiyang661 小时前
# 自研 AST 容错初筛工具:横向评测 Django、PyTorch、TensorFlow 三大开源 Python 框架异常收容风险
python·测试工具·自动化·开源软件·代码规范·devops·代码复审
空奈qwq1 小时前
机器学习入门:从核心概念到建模全流程
人工智能·python·机器学习
IvanCodes1 小时前
Python 基础语法(六):字典与集合
python
lie..1 小时前
30天从零开始学AI应用开发(Day 4):Python 极速入门(上):够用就行,别啃书
人工智能·python·大模型
正经教主1 小时前
【FDE系列】阶段2:Day 38:Shell 脚本 — 把命令串起来自动跑
人工智能·python·fde
鬼先生_sir1 小时前
Docker 完整教程
docker
诺伦1 小时前
多Agent架构下Token成本优化实战:Agent编排策略与预算控制全解析
python·ai agent·token优化·agent编排·多agent架构·llm成本控制