docker实战:基础操作、镜像打包、网络、容器编排

目录

操作

[打包镜像(docker build)](#打包镜像(docker build))

网络

[容器编排(docker compose)](#容器编排(docker compose))


操作

镜像操作:

复制代码
docker images          # 查看镜像
docker pull nginx      # 拉取镜像  
docker rmi nginx       # 删除镜像
docker build -t my-app .  # 构建镜像

容器操作:

复制代码
docker ps              # 查看容器
docker run nginx       # 启动容器
docker stop 容器名      # 停止容器
docker start 容器名     # 启动容器
docker rm 容器名        # 删除容器
docker exec -it 容器名 bash  # 进入容器

日志和监控

复制代码
docker logs 容器名      # 查看日志
docker logs -f 容器名   # 实时日志
docker stats           # 资源监控
docker inspect 容器名   # 查看详情

清理

复制代码
docker container prune  # 清理停止的容器
docker image prune      # 清理悬空镜像
docker volume prune     # 清理未使用的卷
docker system prune     # 清理所有未使用的资源

启动

docker run 常用参数

参数 说明 示例
-d 后台运行 docker run -d nginx
-it 交互模式 docker run -it ubuntu bash
-p 端口映射 -p 8080:80
-v 挂载卷 -v /host:/container
-e 环境变量 -e KEY=value
--name 容器名称 --name my-app
--rm 自动删除 --rm
--network 网络设置 --network my-net

连接

docker exec 常用参数

参数 说明 示例
-it 交互模式 docker exec -it 容器名 bash
-u 指定用户 -u root
-e 环境变量 -e VAR=value

打包镜像(docker build)

docker使用docker file来将指定资源打包成镜像,docker提供了一套命令来编写docker file:

  • from,指定基础镜像

  • run,执行命令

  • copy,复制文件

  • add,添加文件

  • workdir,工作目录

  • expose,暴露端口

  • cmd和entrypoint,启动

from:

复制代码
# 选择官方镜像(推荐)
FROM node:18-alpine        # 轻量级Node.js
FROM python:3.11-slim      # 轻量级Python
FROM nginx:alpine          # 轻量级Nginx
​
# 指定版本(不要用latest)
FROM ubuntu:20.04          # 明确版本号
FROM python:3.11.4-slim    # 具体小版本

run:

复制代码
# 单一命令
RUN apt-get update
​
# 多个命令合并(减少镜像层数)
RUN apt-get update && apt-get install -y \
    curl \
    git \
    vim \
    && rm -rf /var/lib/apt/lists/*  # 清理缓存
​
# 安装Python包
RUN pip install --no-cache-dir flask gunicorn
​
# 安装Node.js包
RUN npm install --production

COPY vs ADD:

复制代码
# COPY - 简单复制(推荐)
COPY package.json .                 # 复制单个文件
COPY src/ ./src/                    # 复制整个目录
COPY --chown=user:group file.txt .  # 复制并设置权限
​
# ADD - 有特殊功能(谨慎使用)
ADD https://example.com/file.tar.gz /tmp/  # 可以下载URL
ADD file.tar.gz /tmp/              # 会自动解压压缩包

workdir:

复制代码
WORKDIR /app           # 进入/app目录
RUN pwd                # 现在在/app
​
WORKDIR src            # 进入/app/src
RUN pwd                # 现在在/app/src
​
# 相当于:
# cd /app
# cd src

expose:

复制代码
EXPOSE 80              # 暴露80端口(HTTP)
EXPOSE 443             # 暴露443端口(HTTPS)
EXPOSE 3000/tcp        # 指定TCP协议
EXPOSE 3000/udp        # 指定UDP协议
​
# 注意:这只是声明,实际映射要在 docker run 时用 -p 参数

CMD vs ENTRYPOINT:

复制代码
# CMD - 默认启动命令(可以被覆盖)
CMD ["nginx", "-g", "daemon off;"]
CMD ["python", "app.py"]
CMD ["npm", "start"]
​
# ENTRYPOINT - 入口点(不容易被覆盖)
ENTRYPOINT ["java", "-jar"]
​
# 组合使用(常见用法)
ENTRYPOINT ["java", "-jar"]
CMD ["app.jar"]  # 运行时可以覆盖:docker run my-app other.jar

下面是构建一个spring boot应用的docker file:

复制代码
# 构建阶段
FROM maven:3.8.6-openjdk-17 AS builder
​
WORKDIR /build
​
# 先复制pom文件(利用缓存)
COPY pom.xml .
RUN mvn dependency:go-offline
​
# 复制源代码
COPY src ./src
​
# 打包应用
RUN mvn package -DskipTests
​
# 运行阶段
FROM openjdk:17-jdk-slim
​
WORKDIR /app
​
# 创建非root用户
RUN groupadd -r spring && useradd -r -g spring spring
USER spring
​
# 复制打包好的jar文件
COPY --from=builder --chown=spring:spring /build/target/*.jar app.jar
​
# 暴露端口
EXPOSE 8080
​
# 启动应用
ENTRYPOINT ["java", "-jar", "app.jar"]

打包指令:

复制代码
docker build -t my-custom-nginx:1.0 .
docker run --name energy-saving-platform -p 9999:9999  -d energy-saving-platform:1.0.0

网络

不同服务打包成不同镜像,启动成不同的容器,容器之间通过URL(IP:端口:接口地址)来访问,这样做没问题。但是IP和端口是可能会变动的,这种改动可能会引起我们需要重新去配置DockerFile,重新打包镜像。docker支持通过配置网络实现通过容器名来访问具体服务。所以在多容器通信的场景下,自定义docker网络会是明智之举。

docker支持以下网络模式:

  • bridge

    • 不自定义网络时,会用一个默认的bridge,也可以自定义一个bridge

    • 优点:简单易用,一个物理机端口能运行多个应用,端口资源占用不严重。

    • 缺点:性能不高,毕竟请求要走好几层过滤。

  • host

    • 直接使用物理机的端口

    • 优点:性能高,毕竟请求不需要走好几层,适用于对请求响应速度有高要求的场景,比如物联网、高并发应用

    • 缺点:不安全,一个物理机端口只能运行一个容器,端口资源占用严重。

  • none

    • 相当于是个容器内网,容器内自己玩儿自己的,不能与外部网络通信。

    • 优点缺点不展开,毕竟基本不会用到。

  • overlay

    • 不同物理机的容器可以直接通信

    • 优点:跨机器

    • 缺点:需要Swarm或K8s集群,提升管理成本

配置示例

查看docker网络相关命令

复制代码
# 查看所有网络
docker network ls
​
# 查看网络详细信息
docker network inspect <network-name>
​
# 查看容器网络配置
docker inspect <container-name> | grep -A 20 NetworkSettings
​
# 测试容器间连通性
docker exec <container1> ping <container2>
​
# 查看端口映射
docker port <container-name>

默认bridge

复制代码
# 启动容器,使用默认bridge网络
docker run -d --name webapp1 -p 8080:80 nginx
docker run -d --name webapp2 -p 8081:80 nginx
​
# 查看网络信息
docker network inspect bridge
​
# 测试连通性(需要通过IP访问)
docker exec webapp1 curl http://172.17.0.3  # 需要知道webapp2的IP

自定义bridge

复制代码
# 创建自定义bridge网络
docker network create my-bridge-network
​
# 启动容器并加入自定义网络
docker run -d --name frontend --network my-bridge-network -p 80:80 nginx
docker run -d --name backend --network my-bridge-network -p 3000:3000 node-app
docker run -d --name database --network my-bridge-network -p 3306:3306 mysql:8.0
​
# 现在容器间可以通过名字访问!
docker exec frontend curl http://backend:3000
docker exec backend ping database
​
# 查看网络详情
docker network inspect my-bridge-network

带子网的自定义bridge

复制代码
# 创建指定子网的bridge网络
docker network create \
  --driver bridge \
  --subnet 192.168.100.0/24 \
  --gateway 192.168.100.1 \
  my-custom-subnet
​
# 启动容器并指定IP
docker run -d --name app1 \
  --network my-custom-subnet \
  --ip 192.168.100.10 \
  my-app:latest
​
docker run -d --name app2 \
  --network my-custom-subnet \
  --ip 192.168.100.11 \
  my-app:latest

host

复制代码
# 使用host网络模式
docker run -d --name nginx-host --network host nginx
​
# 此时nginx直接使用主机的80端口
# 访问: http://localhost:80
​
# 查看进程,可以看到直接使用主机网络
netstat -tlnp | grep :80

none就不展示了,没必要。

overlay需要依赖于docker swarm,docker swarm是一个docker官方提供的容器编排工具,允许将多个 Docker 主机组成一个集群,以集群的方式运行和管理容器。

由于技术选型上是用k8s来编排、管理容器集群,所以不展开docker swarm,只需要知道docker的容器编排有轻量级的swarm和重量级的k8s即可。

容器编排(docker compose)

为什么要容器编排

容器编排,即用配置文件编写好容器之间的依赖关系、启动顺序等。docker提供了docker compose来对容器进行编排,用docker-compose.yml来配置,进行容器编排。多镜像部署且需要通信需要写很多命令,假设一个eureka容器和一个应用容器。

没有 Docker Compose 时,两个问题:

  • 整个过程中要手动执行docker build去重新构建镜像,还要去docker run重新拉起应用,还要来回切目录,很麻烦,而且还要顾及启动顺序,先启动注册中心,然后启动应用。命令又长又复杂。

  • IP地址或者端口变化时,要重新修改配置。

使用 Docker Compose 时,只需要:

  1. 在一个 docker-compose.yml 文件中定义这两个服务。执行一条命令:docker compose up。避免了很多手动命令操作。

  2. 通过配置网络,支持服务之间可以通过名称来访问,规避了IP和端口变化带来的问题。

所有步骤都会自动完成。这极大地提高了开发和测试的效率。

没有docker compose的纯手动操作:

用容器的编排脚本,一个脚本就可以搞定,不用上面那么零碎的手动操作。

docker compose使用docker-compose.yml来编排容器,其中要声明和操作的无非就是:

  • 服务 (Services):每个容器就是一个服务

  • 项目 (Project):一组关联服务的集合

  • 网络 (Networks):容器间的通信网络

  • 数据卷 (Volumes):数据持久化

docker-compose.yml结构如下:

复制代码
version: '3.8'  # Compose 文件版本
​
services:   # 定义所有服务
  service1: # 服务1配置
  service2: # 服务2配置
​
networks:   # 自定义网络
volumes:    # 数据卷定义

常用服务配置项

配置项 说明 示例
image 使用现有镜像 image: nginx:alpine
build 从 Dockerfile 构建 build: .
ports 端口映射 ports: - "80:80"
environment 环境变量 environment: - KEY=VALUE
volumes 数据卷挂载 volumes: - ./data:/app/data
networks 加入网络 networks: - app-network
depends_on 依赖关系 depends_on: - db
restart 重启策略 restart: always

docker-compose.yml:

复制代码
services:
  eureka-server:
    build:
      context: ./eurekaServer
      dockerfile: Dockerfile
    ports:
      - "9001:9001"
    environment:
      - JAVA_OPTS=-Xmx512m -Xms256m
    container_name: eureka-server
    networks:
      - microservice-net
    restart: unless-stopped
​
  # 订单服务
  order-service:
    build:
      context: ./orderServer
      dockerfile: Dockerfile
    ports:
      - "9002:9002"
    environment:
      - JAVA_OPTS=-Xmx512m -Xms256m
    container_name: order-service
    networks:
      - microservice-net
    depends_on:
      - eureka-server
    restart: unless-stopped
networks:
  microservice-net:
    driver: bridge

上面的脚本不能保证启动顺序,需要用健康检查来保证启动顺序:

复制代码
services:
  eureka-server:
    build:
      context: ./eurekaServer
      dockerfile: Dockerfile
    ports:
      - "9001:9001"
    environment:
      - JAVA_OPTS=-Xmx512m -Xms256m
    container_name: eureka-server
    networks:
      - microservice-net
    healthcheck:
      test: ["CMD-SHELL", "timeout 5 bash -c 'cat < /dev/null > /dev/tcp/localhost/9001' || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 18  # 总共等待 3 分钟 (10s * 18)
      start_period: 30s
    restart: unless-stopped
​
  order-service:
    build:
      context: ./orderServer
      dockerfile: Dockerfile
    ports:
      - "9002:9002"
    environment:
      - JAVA_OPTS=-Xmx512m -Xms256m
      - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka-server:9001/eureka/
      - EUREKA_CLIENT_INITIAL-INSTANCE-INFO-REPLICATION_INTERVAL_SECONDS=5
    container_name: order-service
    networks:
      - microservice-net
    depends_on:
      eureka-server:
        condition: service_healthy  # 关键:等待健康状态
    restart: unless-stopped
​
networks:
  microservice-net:
    driver: bridge

启动指令:

复制代码
docker compose up -d
##如果不带-d就会是前台启动
相关推荐
Elastic 中国社区官方博客8 分钟前
在 Elasticsearch 中回填时间序列数据:通过批量 API 加载数月的历史指标数据
大数据·运维·数据库·人工智能·elasticsearch·搜索引擎·全文检索
10mAh24 分钟前
【Linux】CPU 100% 怎么排查?——top、pidstat、jstack 到线程定位实战
linux·运维·服务器
LRL_32 分钟前
深入浅出 Kubernetes 控制器:Deployment 与 StatefulSet 核心区别全景图
云原生·容器·kubernetes
!chen41 分钟前
客户环境 Nginx 配置流式报表与超时排查
运维·nginx
起名真的太难了1 小时前
Docker 项目部署
docker·容器·eureka
狼与自由2 小时前
docker 安装milvus
docker·milvus
KIZIFLOW北泽五金2 小时前
液压系统压力损失怎么降?成因分析与减损实操方案
运维·自动化·新媒体运营·产品运营·流量运营·用户运营·内容运营
介拙2 小时前
Zabbix 7.0 从装到告警触发,我踩了这些坑
运维
爱吃提升2 小时前
VMware虚拟机迁移系统磁盘完整教程(VMware Workstation17)
linux·运维·服务器
摇滚侠2 小时前
《SpringBoot 3:入门与应用实战》第 14 章 打包与部署 制作 Docker 镜像 阅读笔记 43
spring boot·笔记·docker