Docker学习笔记

Docker零基础学习手册

📚 目录

  1. Docker是什么?
  2. 为什么要用Docker?
  3. 核心概念
  4. 安装Docker
  5. 基础命令
  6. 制作镜像
  7. [Docker Compose](#Docker Compose)
  8. 实战案例
  9. 最佳实践
  10. 常见问题

🤔 Docker是什么?

简单比喻

想象Docker就像是**"集装箱"**:

  • 传统方式:就像散装货物,不同的货物需要不同的运输工具
  • Docker方式:把所有东西都装进标准集装箱,任何船都能运输

技术角度

Docker是一个容器化平台 ,它可以把你的应用程序和它需要的所有环境(操作系统、库文件、配置等)打包在一起,形成一个轻量级、可移植的容器

复制代码
没有Docker的世界:
开发环境 ≠ 测试环境 ≠ 生产环境
"在我电脑上好好的啊!" 😭

有了Docker的世界:
开发环境 = 测试环境 = 生产环境
"到哪里都一样!" 😊

🎯 为什么要用Docker?

解决的核心问题

1. 环境一致性问题
复制代码
传统问题:
- 开发用Windows,服务器用Linux
- 本地Python 3.8,服务器Python 3.6
- 少了某个依赖库,程序跑不起来

Docker解决:
- 环境完全打包,到哪都一样
- 一次构建,到处运行
2. 部署复杂性问题
复制代码
传统部署:
1. 安装操作系统
2. 安装各种依赖
3. 配置环境变量
4. 部署应用程序
5. 祈祷没有问题 🙏

Docker部署:
1. docker run my-app
2. 完成! ✅
3. 资源利用率问题
复制代码
虚拟机方式:
[物理服务器]
  ├── [虚拟机1] → [完整OS] → [应用1]
  ├── [虚拟机2] → [完整OS] → [应用2]
  └── [虚拟机3] → [完整OS] → [应用3]
资源浪费,启动慢

Docker方式:
[物理服务器]
  └── [Docker引擎]
      ├── [容器1] → [应用1]
      ├── [容器2] → [应用2]
      └── [容器3] → [应用3]
资源高效,启动快

📖 核心概念

三个核心概念

1. 镜像 (Image) - 🎯

比喻:就像程序安装包或者模板

  • 只读的:不能修改

  • 层级结构:一层层叠加

  • 可共享:多个容器可以使用同一个镜像

    镜像的构成:
    基层:Ubuntu操作系统
    ├── 第二层:安装Java环境
    ├── 第三层:安装Tomcat
    ├── 第四层:复制应用程序
    └── 第五层:设置启动命令

2. 容器 (Container) - 📦

比喻:就像正在运行的程序实例

  • 可读写的:运行时可以修改

  • 隔离的:每个容器相互独立

  • 临时的:删除后数据就没了(除非挂载卷)

    镜像 vs 容器:
    镜像 = 类 (Class)
    容器 = 对象 (Object)

    一个镜像可以创建多个容器
    就像一个类可以创建多个对象

3. 仓库 (Repository) - 🏪

比喻:就像应用商店

重要概念关系图

复制代码
[开发者] 
    ↓ 编写Dockerfile
[Dockerfile] 
    ↓ docker build
[镜像 Image] 
    ↓ docker run
[容器 Container]
    ↓ docker push
[仓库 Repository]

💻 安装Docker

Windows安装

方法1:Docker Desktop (推荐)
复制代码
1. 访问 https://www.docker.com/products/docker-desktop
2. 下载 Docker Desktop for Windows
3. 双击安装包,按提示安装
4. 重启电脑
5. 启动Docker Desktop
验证安装
bash 复制代码
# 打开命令提示符或PowerShell
docker --version
# 应该显示:Docker version 20.10.x

docker run hello-world
# 如果看到 "Hello from Docker!" 说明安装成功

Linux安装 (Ubuntu)

bash 复制代码
# 1. 更新包管理器
sudo apt update

# 2. 安装必要的包
sudo apt install apt-transport-https ca-certificates curl software-properties-common

# 3. 添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 4. 添加Docker仓库
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

# 5. 安装Docker
sudo apt update
sudo apt install docker-ce

# 6. 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker

# 7. 验证安装
sudo docker run hello-world

🔨 基础命令

镜像相关命令

查看镜像
bash 复制代码
# 列出本地所有镜像
docker images

# 或者使用
docker image ls
搜索镜像
bash 复制代码
# 在Docker Hub搜索镜像
docker search nginx
docker search mysql
拉取镜像
bash 复制代码
# 拉取最新版本
docker pull nginx

# 拉取指定版本
docker pull nginx:1.20
docker pull mysql:8.0
删除镜像
bash 复制代码
# 删除指定镜像
docker rmi nginx

# 删除所有未使用的镜像
docker image prune

容器相关命令

运行容器
bash 复制代码
# 基本运行
docker run nginx

# 后台运行
docker run -d nginx

# 指定名称
docker run -d --name my-nginx nginx

# 端口映射
docker run -d -p 8080:80 nginx

# 环境变量
docker run -d -e MYSQL_ROOT_PASSWORD=123456 mysql

# 挂载卷
docker run -d -v /host/path:/container/path nginx
查看容器
bash 复制代码
# 查看运行中的容器
docker ps

# 查看所有容器(包括停止的)
docker ps -a

# 查看容器详细信息
docker inspect container-name
容器操作
bash 复制代码
# 停止容器
docker stop container-name

# 启动容器
docker start container-name

# 重启容器
docker restart container-name

# 删除容器
docker rm container-name

# 强制删除运行中的容器
docker rm -f container-name
进入容器
bash 复制代码
# 进入运行中的容器
docker exec -it container-name bash

# 或者使用sh(如果容器没有bash)
docker exec -it container-name sh

# 查看容器日志
docker logs container-name

# 实时查看日志
docker logs -f container-name

系统相关命令

bash 复制代码
# 查看Docker信息
docker info

# 查看Docker版本
docker version

# 清理系统
docker system prune      # 清理未使用的容器、网络、镜像
docker system prune -a   # 清理所有未使用的资源

# 查看资源使用情况
docker stats

🏗️ 制作镜像

Dockerfile详解

Dockerfile是用来构建镜像的文本文件,包含了一系列的指令。

基本结构
dockerfile 复制代码
# 指定基础镜像
FROM base-image

# 设置工作目录
WORKDIR /app

# 复制文件
COPY source destination

# 运行命令
RUN command

# 暴露端口
EXPOSE port

# 启动命令
CMD ["executable", "param1", "param2"]
常用指令详解
FROM - 指定基础镜像
dockerfile 复制代码
# 使用官方Python镜像
FROM python:3.9

# 使用特定版本
FROM python:3.9-slim

# 使用Ubuntu作为基础
FROM ubuntu:20.04
WORKDIR - 设置工作目录
dockerfile 复制代码
# 设置工作目录(如果不存在会自动创建)
WORKDIR /app

# 相当于 cd /app
COPY 和 ADD - 复制文件
dockerfile 复制代码
# 复制单个文件
COPY app.py /app/

# 复制整个目录
COPY . /app/

# ADD功能更强大,但建议使用COPY
ADD file.tar.gz /app/  # 会自动解压
RUN - 运行命令
dockerfile 复制代码
# 安装软件包
RUN apt-get update && apt-get install -y python3

# 安装Python依赖
RUN pip install -r requirements.txt

# 多个命令用 && 连接(减少层级)
RUN apt-get update && \
    apt-get install -y python3 && \
    rm -rf /var/lib/apt/lists/*
ENV - 设置环境变量
dockerfile 复制代码
# 设置环境变量
ENV PYTHON_VERSION 3.9
ENV APP_HOME /app

# 使用环境变量
WORKDIR $APP_HOME
EXPOSE - 暴露端口
dockerfile 复制代码
# 暴露端口(仅声明,实际映射需要在运行时指定)
EXPOSE 8080
EXPOSE 3000 5000
CMD 和 ENTRYPOINT - 启动命令
dockerfile 复制代码
# CMD:可以被docker run命令覆盖
CMD ["python", "app.py"]

# ENTRYPOINT:不会被覆盖
ENTRYPOINT ["python", "app.py"]

# 组合使用
ENTRYPOINT ["python"]
CMD ["app.py"]

实战案例:Python Flask应用

1. 准备应用文件

app.py

python 复制代码
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello, Docker!'

@app.route('/health')
def health():
    return {'status': 'healthy'}

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

requirements.txt

复制代码
Flask==2.3.3
2. 编写Dockerfile

Dockerfile

dockerfile 复制代码
# 使用Python官方镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 复制依赖文件
COPY requirements.txt .

# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY app.py .

# 暴露端口
EXPOSE 5000

# 设置启动命令
CMD ["python", "app.py"]
3. 构建和运行
bash 复制代码
# 构建镜像
docker build -t my-flask-app .

# 查看构建的镜像
docker images

# 运行容器
docker run -d -p 5000:5000 --name flask-container my-flask-app

# 测试应用
curl http://localhost:5000
# 应该返回:Hello, Docker!

# 查看容器日志
docker logs flask-container

# 进入容器
docker exec -it flask-container bash

优化Dockerfile

多阶段构建
dockerfile 复制代码
# 构建阶段
FROM python:3.9 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt

# 运行阶段
FROM python:3.9-slim
WORKDIR /app

# 从构建阶段复制依赖
COPY --from=builder /root/.local /root/.local

# 复制应用代码
COPY app.py .

# 确保脚本在PATH中
ENV PATH=/root/.local/bin:$PATH

EXPOSE 5000
CMD ["python", "app.py"]
使用.dockerignore
复制代码
# .dockerignore文件
node_modules
*.log
.git
Dockerfile
.dockerignore
README.md

🎼 Docker Compose

什么是Docker Compose?

Docker Compose是用于定义和运行多容器Docker应用程序的工具。

解决的问题
复制代码
单容器的限制:
- 只能运行一个服务
- 手动管理多个容器很复杂
- 容器间网络配置繁琐

Docker Compose的优势:
- 一个文件定义整个应用栈
- 一条命令启动所有服务
- 自动处理容器间网络

docker-compose.yml基础

基本结构
yaml 复制代码
version: '3.8'

services:
  service1:
    image: image-name
    ports:
      - "host-port:container-port"
    environment:
      - ENV_VAR=value
    
  service2:
    build: .
    volumes:
      - ./host-path:/container-path

networks:
  default:
    driver: bridge

volumes:
  volume-name:

实战案例:Web应用 + 数据库

项目结构
复制代码
my-web-app/
├── docker-compose.yml
├── Dockerfile
├── app.py
├── requirements.txt
└── init.sql
docker-compose.yml
yaml 复制代码
version: '3.8'

services:
  # Web应用服务
  web:
    build: .                    # 使用当前目录的Dockerfile构建
    ports:
      - "5000:5000"            # 端口映射
    environment:
      - DB_HOST=db             # 数据库主机名
      - DB_USER=root
      - DB_PASSWORD=123456
      - DB_NAME=myapp
    depends_on:
      - db                     # 依赖数据库服务
    volumes:
      - ./logs:/app/logs       # 日志挂载
    restart: unless-stopped    # 重启策略

  # 数据库服务
  db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - MYSQL_DATABASE=myapp
    ports:
      - "3306:3306"
    volumes:
      - db_data:/var/lib/mysql      # 数据持久化
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    restart: unless-stopped

  # Redis缓存服务
  redis:
    image: redis:alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    restart: unless-stopped

# 定义卷
volumes:
  db_data:
  redis_data:

# 定义网络
networks:
  default:
    driver: bridge
应用代码 (app.py)
python 复制代码
from flask import Flask
import mysql.connector
import redis
import os

app = Flask(__name__)

# 数据库配置
db_config = {
    'host': os.getenv('DB_HOST', 'localhost'),
    'user': os.getenv('DB_USER', 'root'),
    'password': os.getenv('DB_PASSWORD', ''),
    'database': os.getenv('DB_NAME', 'myapp')
}

# Redis配置
redis_client = redis.Redis(host='redis', port=6379, db=0)

@app.route('/')
def hello():
    return 'Hello from Docker Compose!'

@app.route('/db-test')
def db_test():
    try:
        conn = mysql.connector.connect(**db_config)
        cursor = conn.cursor()
        cursor.execute("SELECT VERSION()")
        version = cursor.fetchone()
        conn.close()
        return f'Database version: {version[0]}'
    except Exception as e:
        return f'Database error: {str(e)}'

@app.route('/redis-test')
def redis_test():
    try:
        redis_client.set('test_key', 'Hello Redis!')
        value = redis_client.get('test_key').decode('utf-8')
        return f'Redis value: {value}'
    except Exception as e:
        return f'Redis error: {str(e)}'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
requirements.txt
复制代码
Flask==2.3.3
mysql-connector-python==8.1.0
redis==4.6.0
init.sql
sql 复制代码
-- 初始化数据库脚本
CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO users (name, email) VALUES 
('张三', 'zhangsan@example.com'),
('李四', 'lisi@example.com');

Docker Compose常用命令

bash 复制代码
# 启动所有服务
docker-compose up

# 后台启动
docker-compose up -d

# 重新构建并启动
docker-compose up --build

# 停止所有服务
docker-compose down

# 停止并删除卷
docker-compose down -v

# 查看服务状态
docker-compose ps

# 查看日志
docker-compose logs

# 查看特定服务日志
docker-compose logs web

# 实时查看日志
docker-compose logs -f

# 进入服务容器
docker-compose exec web bash

# 扩展服务(启动多个实例)
docker-compose up -d --scale web=3

🚀 实战案例

案例1:部署.NET Core API

项目结构
复制代码
dotnet-api/
├── docker-compose.yml
├── Dockerfile
├── MyAPI.csproj
├── Program.cs
├── Controllers/
│   └── WeatherController.cs
└── appsettings.json
Dockerfile
dockerfile 复制代码
# 多阶段构建
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src

# 复制项目文件
COPY *.csproj ./
RUN dotnet restore

# 复制源代码并构建
COPY . ./
RUN dotnet publish -c Release -o out

# 运行时镜像
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build /src/out .

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
  CMD curl -f http://localhost:5000/health || exit 1

EXPOSE 5000
ENTRYPOINT ["dotnet", "MyAPI.dll"]
docker-compose.yml
yaml 复制代码
version: '3.8'

services:
  api:
    build: .
    ports:
      - "5000:5000"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production
      - ASPNETCORE_URLS=http://+:5000
      - ConnectionStrings__DefaultConnection=Server=db;Database=MyAPI;User=sa;Password=YourStrong@Passw0rd;
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: mcr.microsoft.com/mssql/server:2019-latest
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=YourStrong@Passw0rd
    ports:
      - "1433:1433"
    volumes:
      - db_data:/var/opt/mssql
    restart: unless-stopped

volumes:
  db_data:

案例2:前端 + 后端 + 数据库完整应用

docker-compose.yml
yaml 复制代码
version: '3.8'

services:
  # 前端服务
  frontend:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./frontend/dist:/usr/share/nginx/html
      - ./frontend/nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - backend
    restart: unless-stopped

  # 后端API服务
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    environment:
      - DATABASE_URL=postgresql://user:password@db:5432/myapp
      - REDIS_URL=redis://redis:6379
    depends_on:
      - db
      - redis
    restart: unless-stopped

  # 数据库服务
  db:
    image: postgres:13
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    restart: unless-stopped

  # 缓存服务
  redis:
    image: redis:alpine
    volumes:
      - redis_data:/data
    restart: unless-stopped

  # 监控服务
  nginx-exporter:
    image: nginx/nginx-prometheus-exporter
    ports:
      - "9113:9113"
    command:
      - -nginx.scrape-uri=http://frontend:80/nginx_status

volumes:
  db_data:
  redis_data:

💡 最佳实践

1. Dockerfile最佳实践

使用合适的基础镜像
dockerfile 复制代码
# ❌ 不好的做法 - 镜像太大
FROM ubuntu:20.04

# ✅ 好的做法 - 使用精简镜像
FROM python:3.9-slim

# ✅ 更好的做法 - 使用Alpine
FROM python:3.9-alpine
减少层级数量
dockerfile 复制代码
# ❌ 不好的做法 - 每个RUN创建一层
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y pip
RUN apt-get clean

# ✅ 好的做法 - 合并命令
RUN apt-get update && \
    apt-get install -y python3 pip && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
利用构建缓存
dockerfile 复制代码
# ✅ 先复制依赖文件,利用缓存
COPY requirements.txt .
RUN pip install -r requirements.txt

# 然后复制应用代码
COPY . .
使用非root用户
dockerfile 复制代码
# 创建用户
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nextjs -u 1001

# 切换用户
USER nextjs

2. 安全最佳实践

扫描漏洞
bash 复制代码
# 使用Docker官方工具扫描
docker scan my-app:latest

# 使用第三方工具
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy image my-app:latest
最小权限原则
yaml 复制代码
# docker-compose.yml
services:
  app:
    image: my-app
    user: "1001:1001"  # 使用非root用户
    read_only: true    # 只读文件系统
    tmpfs:
      - /tmp
      - /var/run

3. 性能优化

多阶段构建
dockerfile 复制代码
# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# 运行阶段
FROM node:16-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
CMD ["node", "index.js"]
使用.dockerignore
复制代码
# .dockerignore
node_modules
*.log
.git
.gitignore
README.md
.env
.nyc_output
coverage
.nyc_output
.coverage
.pytest_cache
__pycache__

4. 日志管理

配置日志驱动
yaml 复制代码
services:
  app:
    image: my-app
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
结构化日志
python 复制代码
import logging
import json

# 配置结构化日志
logging.basicConfig(
    format='%(asctime)s %(levelname)s %(message)s',
    level=logging.INFO
)

# 使用JSON格式
logger = logging.getLogger(__name__)
logger.info(json.dumps({
    'event': 'user_login',
    'user_id': 123,
    'timestamp': '2023-10-01T10:00:00Z'
}))

❓ 常见问题

1. 容器访问问题

问题:容器无法访问外部网络
bash 复制代码
# 解决方案:检查DNS设置
docker run --dns 8.8.8.8 my-app

# 或在docker-compose.yml中设置
services:
  app:
    image: my-app
    dns:
      - 8.8.8.8
      - 8.8.4.4
问题:容器间无法通信
bash 复制代码
# 确保容器在同一网络中
docker network ls
docker network inspect bridge

# 使用服务名称访问
# 在docker-compose中,可以直接使用服务名
curl http://web:5000/api/health

2. 存储和权限问题

问题:数据持久化
yaml 复制代码
# 使用named volume
services:
  db:
    image: mysql:8.0
    volumes:
      - db_data:/var/lib/mysql  # named volume

volumes:
  db_data:  # 定义volume
问题:权限问题
bash 复制代码
# 查看文件权限
ls -la /var/lib/docker/volumes/

# 修改权限
sudo chown -R 1001:1001 /path/to/volume

3. 性能问题

问题:容器启动慢
bash 复制代码
# 检查资源使用
docker stats

# 使用更小的基础镜像
FROM python:3.9-alpine  # 而不是python:3.9
问题:构建慢
bash 复制代码
# 使用构建缓存
docker build --cache-from my-app:latest .

# 使用BuildKit
export DOCKER_BUILDKIT=1
docker build .

4. 调试技巧

进入运行中的容器
bash 复制代码
# 进入容器shell
docker exec -it container-name bash

# 如果没有bash,使用sh
docker exec -it container-name sh

# 以root用户进入
docker exec -it --user root container-name bash
查看容器详细信息
bash 复制代码
# 查看容器配置
docker inspect container-name

# 查看容器进程
docker top container-name

# 查看容器资源使用
docker stats container-name
调试网络问题
bash 复制代码
# 查看网络配置
docker network ls
docker network inspect bridge

# 测试容器间连通性
docker exec container1 ping container2

🎓 学习路径建议

第一阶段:基础入门(1-2周)

复制代码
✅ 理解Docker基本概念
✅ 学会基础命令操作
✅ 会写简单的Dockerfile
✅ 能够运行和管理容器

第二阶段:实践应用(2-3周)

复制代码
✅ 掌握Docker Compose
✅ 能够部署多服务应用
✅ 了解网络和存储
✅ 掌握基本的故障排查

第三阶段:深入优化(2-4周)

复制代码
✅ 掌握最佳实践
✅ 性能优化和安全加固
✅ CI/CD集成
✅ 监控和日志管理

第四阶段:生产应用(持续)

复制代码
✅ 容器编排(Kubernetes)
✅ 微服务架构
✅ DevOps实践
✅ 持续学习新特性

📚 推荐资源

官方文档

实践平台

学习书籍

  • 《Docker技术入门与实战》
  • 《Docker容器与容器云》

视频教程

  • Docker官方YouTube频道
  • 各大技术平台的Docker教程

🎯 总结

Docker是现代应用部署的重要技术,掌握Docker可以:

  1. 提高开发效率:环境一致性,避免"在我机器上正常"问题
  2. 简化部署流程:一键部署,减少运维复杂度
  3. 提升资源利用率:容器化应用占用资源更少
  4. 增强应用可移植性:一次构建,到处运行

学习Docker需要理论与实践结合

  • 先理解概念和原理
  • 然后动手实践操作
  • 最后在实际项目中应用

记住:Docker不仅仅是工具,更是一种思维方式的转变

Happy Dockerizing! 🐳

相关推荐
做运维的阿瑞14 分钟前
Kubernetes网络通信与Pod基础详解:从架构图看K8s核心组件
云原生·容器·kubernetes
梁萌10 小时前
Linux安装BiliNote
linux·运维·服务器·docker·bilinote
行思理11 小时前
docker新手教程
运维·docker·容器
莫陌尛.15 小时前
docker安装中间件
docker·中间件·容器
掘根16 小时前
【Docker】docker run
云原生·eureka
tuokuac17 小时前
虚拟机挂起,重启后主机连接不上虚拟机docker中的mysql?(docker网络状态假死)
网络·mysql·docker
集智飞行19 小时前
docker login方法
运维·docker·容器
不开心就吐槽20 小时前
docker-compose方式快速安装MySQL
运维·docker·容器
芥子沫20 小时前
Docker安装思源笔记&使用指南
笔记·docker·容器·思源笔记
行思理20 小时前
macos 下 docker使用方法 新手教程
macos·docker·容器