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就会是前台启动
相关推荐
SelectDB11 小时前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
曲幽18 小时前
别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了
python·docker·web·pot·translate·libretranslate·arogstranslate
XIAOHEZIcode2 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220703 天前
如何搭建本地yum源(上)
运维
武子康3 天前
调查研究-183 Apple container:Mac 上用轻量 VM 跑 Linux 容器,Swift 会改写本地容器体验吗?
docker·容器·apple
大树885 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠5 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质6 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工6 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
Alsn866 天前
等待学习-学习目录:Docker 容器安全攻防
学习·安全·docker