Dockerfile编写教程,构建自己的镜像 Docker
前言
想用Docker跑自己的项目,不能每次都手动装环境吧?写个Dockerfile,一键构建镜像。本文讲怎么写Dockerfile。
一、什么是Dockerfile
Dockerfile就是一个文本文件,里面写了怎么构建镜像的步骤。
就像写脚本一样,告诉Docker:
- 基于哪个基础镜像
- 装什么软件
- 复制什么文件
- 启动什么命令
二、基本结构
# 基于哪个镜像
FROM nginx:alpine
# 维护者信息
MAINTAINER yourname <email@xx.com>
# 工作目录
WORKDIR /usr/share/nginx/html
# 复制文件
COPY index.html .
# 暴露端口
EXPOSE 80
# 启动命令
CMD ["nginx", "-g", "daemon off;"]
三、常用指令
FROM:基础镜像
FROM nginx:alpine
FROM php:7.4-fpm
FROM mysql:5.7
WORKDIR:工作目录
WORKDIR /app
后面的命令都在这个目录里执行。
COPY:复制文件
COPY index.html /usr/share/nginx/html/
COPY ./src /app
RUN:构建时执行命令
RUN apt-get update && apt-get install -y vim
构建镜像的时候执行。
CMD:容器启动时执行
CMD ["nginx", "-g", "daemon off;"]
容器启动后跑的命令。
EXPOSE:暴露端口
EXPOSE 80
EXPOSE 443
只是声明,实际用的时候还要用-p映射。
ENV:设置环境变量
ENV MYSQL_ROOT_PASSWORD=123456
ENV APP_ENV=production
VOLUME:数据卷
VOLUME ["/var/lib/mysql"]
四、实战例子
例子1:部署静态网站
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
COPY index.html .
COPY about.html .
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
例子2:部署PHP项目
FROM php:7.4-fpm
WORKDIR /var/www/html
COPY . .
RUN docker-php-ext-install mysqli pdo pdo_mysql
EXPOSE 9000
CMD ["php-fpm"]
例子3:Python应用
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]
五、构建镜像
构建命令
docker build -t mynginx:v1 .
-t给镜像起名字和标签.当前目录找Dockerfile
查看构建过程
docker build --progress=plain -t mynginx:v1 .
指定Dockerfile路径
docker build -f docker/Dockerfile -t mynginx:v1 .
六、常用优化技巧
1. 用小镜像
用alpine版本,小很多:
FROM nginx:alpine
2. 合并RUN命令
RUN apt-get update && \
apt-get install -y vim wget && \
rm -rf /var/lib/apt/lists/*
不要写多个RUN,合并成一个,减少层数。
3. .dockerignore文件
不想复制的文件写在.dockerignore里:
.git
node_modules
*.log
4. 多层缓存
把不变的放前面,变的放后面。
# 先复制requirements.txt,装依赖(这个不常变)
COPY requirements.txt .
RUN pip install -r requirements.txt
# 再复制代码(这个常变)
COPY . .
七、常见坑
坑1:Dockerfile文件名不对
必须叫 Dockerfile,首字母大写,没有后缀。
坑2:构建时找不到文件
docker build -t mynginx:v1 .
最后那个点不能少,是构建上下文。
坑3:COPY路径不对
COPY index.html .
这个路径是相对于构建上下文的,不是Dockerfile所在目录。
坑4:CMD和RUN搞混
RUN是构建镜像的时候跑CMD是容器启动的时候跑
坑5:镜像太大
用alpine版本,或者多阶段构建。
八、多阶段构建
# 构建阶段
FROM node:16 AS build
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
这样最终镜像很小,只有编译后的文件。
总结
记住:
FROM基础镜像WORKDIR工作目录COPY复制文件RUN构建时执行CMD启动时执行docker build -t 名字 .构建镜像
最常用:
FROM nginx:alpine
COPY index.html /usr/share/nginx/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
遇到问题加QQ23979811 协助处理
Docker查看容器资源占用,stats命令 Docker
前言
容器跑多了,哪个占CPU、哪个占内存,一眼看出来。本文讲Docker stats命令。
一、基本用法
查看所有运行中的容器
docker stats
输出:
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a1b2c3d4e5f6 mysql 2.50% 500MiB / 2GiB 25.0% 1MB/2MB 10MB/5MB 30
f7e8d9c0b1a2 nginx 0.10% 20MiB / 2GiB 1.0% 5MB/3MB 1MB/0B 5
列解释
- CPU %:CPU使用率
- MEM USAGE / LIMIT:内存使用 / 内存限制
- MEM %:内存使用率
- NET I/O:网络收发流量
- BLOCK I/O:磁盘读写
- PIDS:进程数
二、查看单个容器
docker stats 容器名
只看某一个容器。
三、只看一次,不刷新
默认是实时刷新的,按Ctrl+C退出。
只看一次:
docker stats --no-stream
四、自定义格式
只看CPU和内存
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
JSON格式输出
docker stats --format json --no-stream
五、其他常用命令
查看容器占用磁盘
docker system df
查看单个容器磁盘占用
docker ps -s
看SIZE列,就是容器写的磁盘大小。
查看容器网络IO
docker stats --no-stream
看NET I/O列。
六、常见场景
场景1:哪个容器占CPU高?
docker stats
看CPU %列,高的那个就是。
场景2:哪个容器占内存高?
看MEM USAGE列。
场景3:某个容器网络流量大
看NET I/O列。
七、限制容器资源
跑的时候可以限制CPU和内存:
限制内存512M
docker run -d --memory 512m nginx
限制CPU 0.5核
docker run -d --cpus 0.5 nginx
同时限制
docker run -d \
--memory 512m \
--cpus 0.5 \
nginx
八、常见坑
坑1:stats一直刷新,退不出来
按Ctrl+C退出。
坑2:看不准CPU使用率
Docker stats显示的是CPU使用率百分比,多核的话可能超过100%(比如4核跑满就是400%)。
坑3:内存看的是驻留内存
MEM USAGE是容器实际用的内存,包括缓存。
坑4:容器挂了,stats看不到了
docker stats
只看运行中的容器,停止的看不到。
总结
记住:
docker stats看所有运行中的容器资源占用- 看CPU、内存、网络、磁盘IO
--no-stream只看一次- 跑容器时可以限制资源
最常用:
docker stats
遇到问题加QQ23979811 协助处理
Docker删除所有停止的容器,一键清理 Docker
前言
用Docker久了,一堆停止的容器占磁盘,一个个删太麻烦。本文讲怎么一键清理。
一、查看所有停止的容器
先看看有多少个停止的容器:
docker ps -a
看STATUS列,显示Exited的就是停止的。
只看停止的:
docker ps -a -f status=exited
二、删除所有停止的容器
一键清理
docker container prune
输出:
Total reclaimed space: 1.2GB
直接删掉所有停止的容器。
确认提示
默认会问你:
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N]
输入y确认。
跳过确认
docker container prune -f
加个 -f 直接删,不问。
三、其他清理命令
删除所有没用的镜像
docker image prune
只删悬空镜像(dangling images),就是没有标签的。
删所有没用的镜像(包括没在用的)
docker image prune -a
清理所有没用的东西
docker system prune
包括:
- 停止的容器
- 没用的网络
- 悬空镜像
- 构建缓存
清理所有没用的东西(包括镜像)
docker system prune -a
连没在用的镜像也删了。
清理数据卷
docker volume prune
注意: 这个会删没用的数据卷,里面的数据也没了!
四、手动删除单个容器
如果只想删某一个:
docker rm 容器ID或名字
强制删除运行中的容器:
docker rm -f 容器ID或名字
五、批量删除停止的容器
方法1:用docker rm
docker rm $(docker ps -a -q -f status=exited)
解释:
docker ps -a -q列出所有容器ID-f status=exited只筛停止的docker rm删掉
方法2:用docker container prune
docker container prune -f
推荐用这个,简单。
六、查看磁盘占用
清理之前看看占了多少:
docker system df
输出:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 20 5 10GB 7GB (70%)
Containers 15 5 500MB 400MB (80%)
Local Volumes 8 3 2GB 1GB (50%)
Build Cache - - 1GB 800MB
看RECLAIMABLE列,就是可以回收的。
七、常见场景
场景1:测试完一堆容器,想全清了
docker container prune -f
场景2:磁盘满了,全面清理
docker system prune -a -f --volumes
-a删所有没用的镜像-f不问--volumes连数据卷也删
注意: 这个很猛,数据卷也删了,重要数据先备份!
场景3:只清理镜像,不动容器
docker image prune -a -f
八、常见坑
坑1:删了数据卷,数据没了
docker system prune --volumes
加了 --volumes 会删没用的数据卷。
注意: 数据库的数据卷别删!
坑2:删了镜像,重新拉要很久
docker image prune -a
把所有没在用的镜像都删了,下次用还要重新拉。
建议: 常用镜像留着,别全删。
坑3:误删了运行中的容器?
docker container prune 只删停止的,运行中的删不了。
放心,安全。
坑4:删了容器,数据卷还在
docker rm 容器名
只删容器,数据卷还在。
想连数据卷一起删:
docker rm -v 容器名
九、定期清理脚本
写个脚本,定期清理:
#!/bin/bash
# 清理停止的容器
docker container prune -f
# 清理悬空镜像
docker image prune -f
# 清理没用的网络
docker network prune -f
加到crontab,每周跑一次:
0 3 * * 0 /home/clean-docker.sh
总结
记住:
docker container prune删所有停止的容器docker image prune -a删所有没用的镜像docker system prune全面清理- 删数据卷要小心,别把数据库删了
最常用:
docker container prune -f
遇到问题加QQ23979811 协助处理
Docker数据卷挂载,容器数据持久化 Docker
前言
删了Docker容器,数据全没了?那是因为你没挂数据卷。本文讲怎么用数据卷让容器数据持久化。
一、为什么需要数据卷
容器里的数据,容器删了就没了。
docker run -d --name mysql mysql:5.7
# 删了容器,数据就没了
docker rm -f mysql
解决: 把数据存到宿主机,容器删了数据还在。
二、三种数据持久化方式
1. 绑定挂载(bind mount)
把宿主机的目录直接挂到容器里。
docker run -v /宿主机路径:/容器路径 镜像名
例子:
docker run -d \
-v /data/mysql:/var/lib/mysql \
mysql:5.7
特点: 简单直接,数据在你自己的目录里。
2. 命名卷(named volume)
Docker管理的数据卷。
docker volume create mydata
docker run -v mydata:/var/lib/mysql mysql:5.7
特点: Docker帮你管理位置,不用你关心存在哪。
3. 临时挂载(tmpfs)
存在内存里,重启就没。
docker run --tmpfs /tmp 镜像名
特点: 临时用,存敏感数据。
三、常用场景
场景1:MySQL数据持久化
docker run -d \
--name mysql \
-v /data/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
mysql:5.7
场景2:Nginx挂载网站文件
docker run -d \
--name nginx \
-v /data/www:/usr/share/nginx/html \
-p 80:80 \
nginx
场景3:挂载配置文件
docker run -d \
-v /data/nginx/nginx.conf:/etc/nginx/nginx.conf \
nginx
场景4:挂载日志
docker run -d \
-v /data/logs/nginx:/var/log/nginx \
nginx
四、Docker Compose里的挂载
services:
mysql:
image: mysql:5.7
volumes:
- /data/mysql:/var/lib/mysql
# 或者用命名卷
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
五、常用命令
查看所有数据卷
docker volume ls
查看数据卷详情
docker volume inspect 数据卷名
删除没用的数据卷
docker volume prune
查看容器挂载
docker inspect -f '{{.Mounts}}' 容器名
六、只读挂载
只想让容器读,不让写:
docker run -v /data/www:/usr/share/nginx/html:ro nginx
后面加个 :ro 就是只读。
七、常见坑
坑1:改了配置文件不生效
挂了配置文件,改了宿主机的文件,重启容器还是旧的。
原因: 容器没真正重启。
解决:
docker restart 容器名
坑2:权限问题
挂载的目录,容器里的用户读不了。
原因: 宿主机目录权限不对。
解决:
chmod -R 777 /data/mysql
坑3:Windows/Mac路径问题
Windows路径写法不一样:
docker run -v D:\data:/var/lib/mysql mysql
Mac/Linux用:
docker run -v /Users/xxx/data:/var/lib/mysql mysql
坑4:挂载文件不存在
宿主机的文件不存在,Docker会自动建一个目录。
比如:
docker run -v /data/nginx.conf:/etc/nginx/nginx.conf nginx
如果 /data/nginx.conf 不存在,Docker会建一个叫 nginx.conf 的目录,容器里就挂错了。
解决: 先创建文件:
touch /data/nginx.conf
坑5:数据卷删了数据就没了
docker volume rm mydata
数据卷删了,里面的数据也没了。
解决: 重要数据定期备份。
八、最佳实践
- 数据库一定要挂载数据卷,不然容器删了数据就没了
- 配置文件挂载到宿主机,改起来方便
- 日志挂载到宿主机,方便查看和切割
- 网站文件挂载到宿主机,更新代码不用重新打镜像
总结
记住:
-v 宿主机路径:容器路径就是挂载- 数据库一定要挂数据卷
- 删容器不删数据,因为数据在宿主机
- 挂载文件不存在会变成目录,要注意
最常用:
docker run -v /data/mysql:/var/lib/mysql mysql
遇到问题加QQ23979811 协助处理
Docker端口映射,-p参数用法详解 Docker
前言
容器跑起来了,但外部访问不了,就是端口没映射好。本文讲Docker端口映射的各种用法。
一、什么是端口映射
Docker容器有自己的内部网络,外部要访问容器里的服务,得把宿主机的端口映射到容器的端口。
二、基本用法
格式
-p 宿主机端口:容器端口
例子
docker run -d -p 8080:80 nginx
意思:访问宿主机的8080端口,转发到容器的80端口。
浏览器访问
http://服务器IP:8080
三、各种写法
1. 指定宿主机端口和容器端口
-p 8080:80
2. 只指定容器端口,宿主机随机分配
docker run -d -P nginx
大写P,宿主机随机找个空闲端口。
3. 绑定指定IP
-p 127.0.0.1:8080:80
只允许本机访问,外网访问不了。
4. UDP端口
-p 53:53/udp
5. 映射多个端口
docker run -d \
-p 80:80 \
-p 443:443 \
-p 2222:22 \
nginx
四、查看端口映射
查看容器端口
docker port 容器名
输出:
80/tcp -> 0.0.0.0:8080
查看详细信息
docker ps
看PORTS列。
五、Docker Compose里的端口映射
services:
nginx:
image: nginx
ports:
- "80:80"
- "443:443"
- "127.0.0.1:8080:80"
六、常见场景
场景1:跑Nginx
docker run -d -p 80:80 --name mynginx nginx
场景2:跑MySQL
docker run -d -p 3306:3306 --name mysql \
-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
场景3:跑Redis
docker run -d -p 6379:6379 --name redis redis
场景4:多个容器跑同一个端口
比如跑两个Nginx,分别用不同端口:
docker run -d -p 8081:80 --name nginx1 nginx
docker run -d -p 8082:80 --name nginx2 nginx
七、端口被占用怎么办
报错
Bind for 0.0.0.0:80 failed: port is already allocated
查谁占用了80端口
netstat -tlnp | grep :80
# 或者
lsof -i:80
解决
- 换个端口:
-p 8080:80 - 或者把占用端口的程序关掉
八、端口映射的坑
坑1:只映射了容器端口,没映射宿主机端口
docker run -d -p 80 nginx
这样宿主机随机分配端口,不好记。
坑2:防火墙没开
端口映射了,但防火墙挡了,外网还是访问不了。
解决: 开放端口:
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --reload
坑3:改不了端口映射
容器启动后,想改端口映射,改不了。
解决: 删掉容器重新跑。容器数据用卷挂载了就不怕丢。
坑4:绑定127.0.0.1后外网访问不了
-p 127.0.0.1:8080:80
这个只能本机访问,外网访问不了。
原因: 故意绑的本机。
解决: 改成 0.0.0.0:8080:80 或者直接 8080:80。
总结
记住:
- 基本格式:
-p 宿主机端口:容器端口 - 多个端口就写多个
-p - 端口被占用就换一个
- 防火墙也要开
常用:
docker run -d -p 80:80 --name nginx nginx
遇到问题加QQ23979811 协助处理
Docker进入容器内部,exec和attach区别 Docker
前言
要进容器里改配置、看日志,用什么命令?docker exec和docker attach有什么区别?本文讲清楚。
一、docker exec(推荐)
作用
在运行中的容器里开一个新进程。
进入容器
docker exec -it 容器名 /bin/bash
或者:
docker exec -it 容器名 sh
参数说明
| 参数 | 说明 |
|---|---|
| -i | 保持交互 |
| -t | 分配终端 |
| -it | 合起来用 |
退出
输入 exit 或者按 Ctrl+D。
关键: 退出后容器还在运行,不受影响。
执行单个命令
不进交互模式,直接执行命令:
docker exec 容器名 ls /var/www/html
docker exec 容器名 cat /etc/nginx/nginx.conf
docker exec 容器名 php -v
二、docker attach
作用
连接到容器正在运行的主进程。
用法
docker attach 容器名
危险!
退出会导致容器停止!
按 Ctrl+C 退出后,容器就停了。
怎么安全退出
按 Ctrl+P 然后 Ctrl+Q,这样退出不会停容器。
三、exec和attach区别
| 对比 | exec | attach |
|---|---|---|
| 原理 | 开新进程 | 连接主进程 |
| 退出后容器 | 继续运行 | 会停止 |
| 常用场景 | 进容器操作 | 看主进程输出 |
| 推荐度 | 推荐 | 不推荐 |
记住: 日常用exec,别用attach。
四、常见场景
场景1:进容器改配置
docker exec -it mynginx /bin/bash
场景2:在容器里执行PHP命令
docker exec myphp php artisan migrate
场景3:看容器里的日志文件
docker exec mynginx tail -f /var/log/nginx/access.log
场景4:容器里没bash
有些精简镜像没有bash,用sh:
docker exec -it 容器名 sh
场景5:以root用户进入
docker exec -u root -it 容器名 /bin/bash
五、如果容器没bash怎么办
用nsenter
# 先拿容器PID
PID=$(docker inspect --format "{{.State.Pid}}" 容器名)
# 进入
nsenter --target $PID --mount --uts --ipc --net --pid
或者用docker run
用同一个镜像开个交互式容器:
docker run -it --rm 镜像名 /bin/bash
六、常用命令汇总
| 命令 | 说明 |
|---|---|
| docker exec -it 容器名 /bin/bash | 进容器 |
| docker exec 容器名 命令 | 执行命令 |
| docker exec -u root -it 容器名 /bin/bash | 以root进 |
| docker attach 容器名 | 连接主进程(慎用) |
常见坑
坑1:attach退出后容器停了
用attach进去,按Ctrl+C退出,容器就停了。
解决: 用exec,或者Ctrl+P Ctrl+Q退出。
坑2:进容器报/ bin/bash not found
镜像里没有bash。
解决: 用sh:
docker exec -it 容器名 sh
坑3:进容器报permission denied
不是root用户,权限不够。
解决: 加 -u root:
docker exec -u root -it 容器名 /bin/bash
坑4:exec进不去,说容器没运行
容器停了,exec进不去。
解决: 先启动容器:
docker start 容器名
docker exec -it 容器名 /bin/bash
坑5:多个终端连同一个容器
exec可以开多个终端,互不影响。
这是exec比attach好的地方,attach只能连一个。
总结
记住两点:
- 日常用
docker exec -it 容器名 /bin/bash - 别用attach,退出会把容器搞停
补充: 精简镜像没有bash,用sh代替。
遇到问题加QQ23979811 协助处理
Docker查看容器IP,docker inspect命令 Docker
前言
容器之间要互相通信,得知道容器的IP。本文讲怎么用docker inspect查看容器IP和详细信息。
一、查看容器IP
最简单的方法
docker inspect 容器名
输出一大串JSON,找IPAddress字段。
只看IP
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 容器名
直接输出IP地址,比如:172.17.0.2
查看所有运行中容器的IP
docker ps -q | xargs docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
输出:
/mynginx - 172.17.0.2
/mymysql - 172.17.0.3
/myphp - 172.17.0.4
二、docker inspect常用用法
查看容器挂载
docker inspect -f '{{.Mounts}}' 容器名
查看容器启动命令
docker inspect -f '{{.Config.Cmd}}' 容器名
查看容器环境变量
docker inspect -f '{{.Config.Env}}' 容器名
查看容器端口映射
docker inspect -f '{{.NetworkSettings.Ports}}' 容器名
查看容器网络
docker inspect -f '{{.NetworkSettings.Networks}}' 容器名
查看容器状态
docker inspect -f '{{.State.Status}}' 容器名
查看容器启动时间
docker inspect -f '{{.State.StartedAt}}' 容器名
查看容器日志路径
docker inspect -f '{{.LogPath}}' 容器名
三、查看镜像信息
查看镜像详细信息
docker inspect 镜像名
查看镜像作者
docker inspect -f '{{.Author}}' nginx
查看镜像默认启动命令
docker inspect -f '{{.Config.Cmd}}' nginx
四、容器之间怎么通信
用容器名通信(推荐)
Docker默认网络里,容器可以用容器名互相访问:
# 在nginx容器里ping mysql
docker exec mynginx ping mysql
不用记IP,直接用容器名就行。
用自定义网络
# 创建网络
docker network create mynet
# 容器加入网络
docker run --name mysql --network mynet -d mysql:5.7
docker run --name nginx --network mynet -d nginx
五、常见场景
场景1:Nginx反向代理连PHP
nginx配置里:
fastcgi_pass php:9000;
这里的php就是容器名,Docker会自动解析成容器IP。
场景2:PHP连MySQL
<?php
$pdo = new PDO('mysql:host=mysql;dbname=mydb', 'root', '123456');
?>
host填mysql,就是MySQL容器的名字。
六、容器IP会变吗?
会的。
容器重启后,IP可能会变。所以不要硬编码IP,用容器名通信最稳。
如果要固定IP: 用自定义网络,指定静态IP。
# docker-compose.yml
services:
mysql:
networks:
mynet:
ipv4_address: 172.20.0.10
常见坑
坑1:inspect输出太多,找不到IP
解决: 用 -f 参数过滤,只看你要的字段。
坑2:容器停了就看不到IP
容器停止状态下,IPAddress是空的。
解决: 先启动容器:docker start 容器名
坑3:不同网络的容器互相ping不通
原因: 容器在不同网络里。
解决: 把它们加到同一个网络:
docker network connect mynet 容器名
坑4:用容器名ping不通
原因: 不是默认网络,或者Docker版本太老。
解决: 用自定义网络,或者直接用IP。
坑5:host网络模式看不到IP
用 --network=host 启动的容器,IP和宿主机一样。
解决: 不用查了,就是宿主机的IP。
总结
常用命令:
| 命令 | 说明 |
|---|---|
| docker inspect 容器名 | 看容器全部信息 |
| docker inspect -f '{{.NetworkSettings.IPAddress}}' 容器名 | 只看IP |
| docker inspect -f '{{.Mounts}}' 容器名 | 看挂载 |
| docker inspect -f '{{.Config.Env}}' 容器名 | 看环境变量 |
记住: 容器之间用容器名通信,别硬编码IP,重启就变了。
遇到问题加QQ23979811 协助处理
Docker容器内时间和宿主机不一致修复 Docker
前言
Docker容器里的时间和宿主机差了8个小时,日志时间不对,定时任务也跑偏。本文讲怎么修复容器时区问题。
一、问题现象
# 宿主机时间
date
# 输出:Thu Oct 8 08:14:01 CST 2026
# 容器里时间
docker exec 容器名 date
# 输出:Thu Oct 8 00:14:01 UTC 2026
差了8个小时,因为容器默认用UTC时区。
二、查看容器时区
docker exec 容器名 date
或者:
docker exec 容器名 cat /etc/timezone
三、修复方法
方法1:挂载时区文件(推荐)
启动容器时挂载宿主机的时区文件:
docker run -v /etc/localtime:/etc/localtime:ro 镜像名
这样容器就和宿主机用同一个时区了。
方法2:设置环境变量
docker run -e TZ=Asia/Shanghai 镜像名
方法3:进容器手动改
# 进容器
docker exec -it 容器名 bash
# 装时区数据
apt-get update && apt-get install -y tzdata
# 设置时区
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
# 验证
date
方法4:Docker Compose设置
在docker-compose.yml里加:
services:
app:
image: xxx
environment:
- TZ=Asia/Shanghai
volumes:
- /etc/localtime:/etc/localtime:ro
四、PHP容器额外设置
PHP的时区和系统时区是两回事,还要改php.ini:
[Date]
date.timezone = Asia/Shanghai
或者在代码里设:
<?php
date_default_timezone_set('Asia/Shanghai');
?>
五、MySQL容器额外设置
MySQL的时区也要改:
-- 查看当前时区
SELECT @@global.time_zone;
-- 设置为东八区
SET GLOBAL time_zone = '+8:00';
永久生效改my.cnf:
[mysqld]
default-time-zone = '+8:00'
六、验证
# 宿主机时间
date
# 容器时间
docker exec 容器名 date
两个时间一致就对了。
常见坑
坑1:改了时区不生效
改了时区文件,重启容器又变回UTC了。
原因: 容器重启后文件系统重置了。
解决: 用挂载的方式,不要进容器改。
坑2:只改了系统时区,PHP时区不对
系统时间对了,但PHP date()还是错的。
原因: PHP有自己的时区设置。
解决: 改php.ini的date.timezone。
坑3:日志时间不对
日志里的时间还是UTC。
原因: 程序启动时读的时区,改了时区要重启程序。
解决: 重启容器或重启程序。
坑4:Windows/Mac Docker Desktop
Windows和Mac上Docker Desktop的时区处理不一样。
解决: 直接用TZ环境变量最稳。
坑5:时区列表找不到Asia/Shanghai
原因: 容器里没装tzdata。
解决: 先装tzdata:
apt-get install -y tzdata
总结
最稳的方法:
- 挂载
/etc/localtime:/etc/localtime:ro - 加环境变量
TZ=Asia/Shanghai - PHP改
date.timezone - MySQL改
default-time-zone
记住: 时区不一致是Docker最常见的问题之一,部署完第一件事先验证时间。
遇到问题加QQ23979811 协助处理
Docker Compose部署LNMP环境完整示例 Docker
前言
手动装Nginx、PHP、MySQL太麻烦,用Docker Compose一键部署LNMP环境,几分钟搞定。
一、项目结构
lnmp/
├── docker-compose.yml
├── nginx/
│ ├── conf.d/
│ │ └── default.conf
│ └── nginx.conf
├── php/
│ └── php.ini
├── mysql/
│ └── my.cnf
└── www/
└── index.php
二、docker-compose.yml
version: '3'
services:
nginx:
image: nginx:latest
container_name: lnmp_nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./www:/var/www/html
depends_on:
- php
networks:
- lnmp
php:
image: php:fpm
container_name: lnmp_php
volumes:
- ./www:/var/www/html
- ./php/php.ini:/usr/local/etc/php/php.ini
networks:
- lnmp
mysql:
image: mysql:5.7
container_name: lnmp_mysql
ports:
- "3306:3306"
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: mydb
networks:
- lnmp
networks:
lnmp:
driver: bridge
三、Nginx配置
nginx/conf.d/default.conf
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
include fastcgi_params;
}
}
四、PHP配置
php/php.ini
[PHP]
date.timezone = Asia/Shanghai
upload_max_filesize = 20M
post_max_size = 20M
memory_limit = 128M
五、MySQL配置
mysql/my.cnf
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
六、测试文件
www/index.php
<?php
phpinfo();
?>
七、启动
cd lnmp
docker-compose up -d
查看状态
docker-compose ps
访问
http://localhost
能看到phpinfo页面就是成功了。
八、常用命令
| 命令 | 说明 |
|---|---|
| docker-compose up -d | 启动 |
| docker-compose down | 停止并删除容器 |
| docker-compose restart | 重启 |
| docker-compose logs -f | 看日志 |
| docker-compose exec php bash | 进PHP容器 |
| docker-compose exec mysql bash | 进MySQL容器 |
九、连接MySQL
从宿主机连接
mysql -h 127.0.0.1 -P 3306 -u root -p123456
从PHP连接
<?php
$pdo = new PDO('mysql:host=mysql;dbname=mydb', 'root', '123456');
echo "连接成功";
?>
注意:host填mysql,不是localhost,是docker-compose.yml里的服务名。
十、安装PHP扩展
进入PHP容器
docker-compose exec php bash
安装pdo_mysql
docker-php-ext-install pdo_mysql
docker-php-ext-install mysqli
重启PHP
docker-compose restart php
常见坑
坑1:Nginx报502
502 Bad Gateway,原因是PHP容器没启动,或者地址不对。
解决:确认PHP容器在运行,fastcgi_pass填服务名php:9000。
坑2:MySQL启动失败
原因:数据目录权限不对,或者密码没设。
解决:确认MYSQL_ROOT_PASSWORD设了,数据目录权限改成777。
坑3:文件修改不生效
改了www里的文件,浏览器刷新没变。
解决:确认volumes挂载了./www:/var/www/html。
坑4:端口被占用
port is already allocated,原因是宿主机80端口被占了。
解决:改端口,比如改成8080。
坑5:数据丢失
删了容器,MySQL数据没了。
解决:一定要挂载数据卷,./mysql/data:/var/lib/mysql。
总结
部署五步:建项目目录结构,写docker-compose.yml,写配置文件,docker-compose up -d启动,浏览器访问测试。
记住:数据一定要挂载,不然删容器数据就没了。
遇到问题加QQ23979811 协助处理
Docker镜像占用空间过大,清理无用镜像容器 Docker
前言
用了一段时间Docker,磁盘满了。docker images一看,一堆旧镜像和停止的容器占着空间。本文讲怎么清理Docker空间。
一、查看Docker占用空间
docker system df
输出:
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 50 10 15GB 10GB
Containers 30 10 500MB 400MB
Local Volumes 20 5 2GB 1.5GB
RECLAIMABLE 就是可以回收的空间。
二、查看镜像列表
docker images
看REPOSITORY、TAG、SIZE列。
三、清理停止的容器
删除单个容器
docker rm 容器ID/容器名
删除所有停止的容器
docker container prune
会提示确认,输入y。
加-f强制删除
docker container prune -f
不提示直接删。
四、清理无用镜像
删除单个镜像
docker rmi 镜像ID/镜像名
删除所有悬空镜像
悬空镜像就是 <none>:<none> 那些,构建中间产生的。
docker image prune
删除所有未被使用的镜像
docker image prune -a
注意:这会删掉所有没被容器用着的镜像,小心。
五、清理无用卷
查看卷
docker volume ls
删除无用卷
docker volume prune
六、清理无用网络
docker network prune
七、一键全部清理
docker system prune
清理:
- 停止的容器
- 无用网络
- 悬空镜像
- 构建缓存
连镜像一起删
docker system prune -a
把没被用的镜像也删掉。
加时间过滤
只删24小时前的:
docker system prune -a --filter "until=24h"
八、常见清理场景
场景1:磁盘快满了
# 先看占了多少
docker system df
# 清理停止的容器
docker container prune -f
# 清理悬空镜像
docker image prune -f
# 清理无用卷
docker volume prune -f
场景2:想彻底清理
docker system prune -a -f --volumes
九、手动清理某个镜像
找到镜像ID
docker images
删除
docker rmi 镜像ID
强制删除
如果镜像被停止的容器引用了,先删容器:
docker rm 容器ID
docker rmi 镜像ID
或者强制删:
docker rmi -f 镜像ID
常见坑
坑1:删镜像报错
Error response from daemon: conflict: unable to delete image (must be forced) - image is being used by stopped container
原因: 有停止的容器在用这个镜像。
解决: 先删容器,或者强制删。
坑2:删了镜像,数据还在
镜像删了,但卷还在,数据没丢。
原因: 数据存在卷里,和镜像分开的。
这是好事! 重新起容器挂载同一个卷,数据就回来了。
坑3:docker system prune删多了
把还要用的镜像也删了。
解决: 重要镜像别删,重新pull就行。
坑4:清理完磁盘还是满的
Docker清理了,但磁盘还是100%。
原因: Docker日志文件太大了。
解决: 清理容器日志:
truncate -s 0 /var/lib/docker/containers/*/*-json.log
或者配置日志大小限制。
坑5:构建缓存占空间
docker builder prune
清理构建缓存。
十、定期清理
可以加个定时任务,每周清理一次:
crontab -e
加:
0 3 * * 0 /usr/bin/docker system prune -a -f --filter "until=168h"
每周日凌晨3点清理一周前的。
总结
常用清理命令:
| 命令 | 说明 |
|---|---|
| docker system df | 看占用空间 |
| docker container prune | 清理停止的容器 |
| docker image prune | 清理悬空镜像 |
| docker volume prune | 清理无用卷 |
| docker system prune -a | 一键全清 |
记住: 定期清理,别等磁盘满了再弄。
遇到问题加QQ23979811 协助处理
Docker容器启动失败,查看容器日志排查错误 Docker
前言
Docker容器启动后马上就退出了,不知道为什么。本文讲怎么查看容器日志,排查启动失败的原因。
一、查看容器状态
列出所有容器
docker ps -a
看STATUS列:
Up就是正常运行Exited (1)就是异常退出了
查看指定容器状态
docker ps -a | grep 容器名
二、查看容器日志
基本用法
docker logs 容器名/容器ID
实时查看日志
docker logs -f 容器名
查看最后100行
docker logs --tail 100 容器名
带时间戳
docker logs -t 容器名
查看最近10分钟的日志
docker logs --since 10m 容器名
三、常见启动失败原因
原因1:程序启动就退出
比如你跑的是个命令行程序,执行完就退出了,容器当然也跟着退。
解决: 前台运行程序,别后台跑。
# 错误:后台运行
CMD service nginx start
# 正确:前台运行
CMD nginx -g "daemon off;"
原因2:配置文件错误
比如nginx配置写错了,启动失败。
日志里会有:
nginx: [emerg] unknown directive "xxx"
解决: 根据日志提示改配置。
原因3:端口被占用
宿主机的端口已经被别的程序占了。
日志里会有:
Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use
解决: 换个端口,或者把占用端口的程序关掉。
# 查谁占用了80端口
netstat -tlnp | grep :80
原因4:挂载的文件不存在
-v挂载的宿主机路径不存在。
日志里会有:
no such file or directory
解决: 先创建宿主机目录。
mkdir -p /data/www
原因5:权限问题
挂载的目录权限不对,程序读不了。
日志里会有:
Permission denied
解决: 改目录权限:
chmod 755 /data/www
原因6:环境变量没设
程序需要的环境变量没传进去。
日志里会有:
Environment variable XXX is not set
解决: 启动时传环境变量:
docker run -e MYSQL_ROOT_PASSWORD=123456 mysql
四、排查步骤
第一步:看状态
docker ps -a
确认容器是Exited状态。
第二步:看日志
docker logs 容器名
日志最后几行就是报错原因。
第三步:进容器看
如果日志不够详细,进容器里手动跑:
docker run -it 镜像名 /bin/bash
进去后手动执行启动命令,看报什么错。
第四步:检查配置
挂载的配置文件对不对,环境变量有没有。
五、常用命令汇总
| 命令 | 说明 |
|---|---|
| docker ps -a | 看所有容器状态 |
| docker logs 容器名 | 看日志 |
| docker logs -f 容器名 | 实时看日志 |
| docker logs --tail 100 容器名 | 看最后100行 |
| docker inspect 容器名 | 看容器详细信息 |
| docker exec -it 容器名 /bin/bash | 进运行中的容器 |
| docker run -it 镜像 /bin/bash | 用镜像开个交互式容器 |
六、查看容器详细信息
docker inspect 容器名
能看到挂载、环境变量、网络等所有信息。
只看挂载信息
docker inspect -f '{{.Mounts}}' 容器名
只看启动命令
docker inspect -f '{{.Config.Cmd}}' 容器名
常见坑
坑1:容器启动马上退出,日志是空的
docker logs 容器名
什么都没有。
原因: 程序本身就没输出,或者启动太早就挂了。
解决: 用 docker run -it 镜像 /bin/bash 进去手动跑。
坑2:改了配置不生效
改了挂载的配置文件,重启容器还是不生效。
原因: 容器没真正重启,或者配置文件路径不对。
解决: 强制重启:
docker restart 容器名
坑3:日志一直刷,停不下来
docker logs -f 容器名
日志一直在刷。
解决: 按 Ctrl+C 退出。
坑4:容器删除了日志就没了
容器删了,日志也跟着没了。
解决: 重要日志挂载到宿主机。
坑5:看日志找不到容器ID
容器太多,不知道哪个是哪个。
解决: 启动的时候给容器起个好记的名字:
docker run --name mynginx -d nginx
总结
排查三步:
docker ps -a看容器状态docker logs 容器名看报错- 按日志提示改问题
记住: 容器启动失败别慌,看日志就行,日志里都写了原因。
遇到问题加QQ23979811 协助处理
Docker 镜像加速配置 Docker
Docker 镜像加速配置
国内拉取 Docker 镜像很慢,配置镜像加速器很有必要。
1. 为什么要加速
Docker Hub 在国外,国内拉镜像经常超时,配置加速器能快很多。
2. 配置方法
Linux(CentOS/Ubuntu):
编辑配置文件:
mkdir -p /etc/docker
vi /etc/docker/daemon.json
写入内容:
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com"
]
}
重启生效:
systemctl daemon-reload
systemctl restart docker
3. 常用加速器
# 中科大
https://docker.mirrors.ustc.edu.cn
# 网易
https://hub-mirror.c.163.com
# 阿里(需要自己的地址)
https://xxxx.mirror.aliyuncs.com
4. 验证是否生效
docker info
看到 Registry Mirrors 下面有地址就说明成功了。
5. 常见问题
1)拉取还是很慢:
- 换个加速器试试
- 网络问题
2)配置不生效:
- 检查 json 格式对不对
- 重启 docker
3)企业内网:
- 可以自己搭建私有镜像仓库
- 或者用阿里云私有镜像服务
6. 常用镜像源
# 官方
docker pull nginx
docker pull mysql
docker pull redis
# 指定版本
docker pull nginx:1.25
docker pull mysql:8.0
总结
Docker 镜像加速核心:
- 配置 daemon.json
- 用国内加速器地址
- 重启 docker 生效
- docker info 验证
做运维开发,Docker 镜像加速是第一步。
Docker 常用命令汇总 Docker
Docker 常用命令汇总
Docker 现在是开发必备工具,整理一份常用命令清单,记不住随时翻。
1. 镜像管理
# 查看本地镜像
docker images
# 搜索镜像
docker search nginx
# 拉取镜像
docker pull nginx:latest
# 删除镜像
docker rmi nginx:latest
# 导出镜像
docker save -o nginx.tar nginx:latest
# 导入镜像
docker load -i nginx.tar
2. 容器管理
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 启动容器
docker start nginx
# 停止容器
docker stop nginx
# 重启容器
docker restart nginx
# 删除容器
docker rm nginx
# 强制删除运行中的容器
docker rm -f nginx
3. 运行容器
# 后台运行 nginx
docker run -d --name mynginx -p 80:80 nginx
# 参数说明:
# -d:后台运行
# --name:容器名
# -p:端口映射(主机:容器)
# -v:目录挂载(主机:容器)
# 进入容器内部
docker exec -it mynginx bash
# 查看容器日志
docker logs mynginx
# 实时查看日志
docker logs -f mynginx
4. 查看容器信息
# 查看容器详细信息
docker inspect mynginx
# 查看容器占用资源
docker stats
# 查看容器端口映射
docker port mynginx
5. 数据卷
# 创建数据卷
docker volume create mydata
# 查看所有数据卷
docker volume ls
# 挂载数据卷运行容器
docker run -d -v mydata:/data nginx
# 删除数据卷
docker volume rm mydata
6. Docker Compose
# 启动服务
docker-compose up -d
# 停止服务
docker-compose down
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
docker-compose.yml 示例:
version: '3'
services:
nginx:
image: nginx
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
7. 清理命令
# 删除所有停止的容器
docker container prune
# 删除所有无用镜像
docker image prune -a
# 删除所有无用数据卷
docker volume prune
# 一键清理所有无用资源
docker system prune -a
总结
Docker 常用命令就这几类:
- 镜像: pull / images / rmi
- 容器: run / ps / stop / rm / exec
- 日志: logs / stats
- Compose: up / down
日常开发把这些命令用熟就够了,不用背,多敲几次自然记住。
Docker 网络模式详解 Docker
Docker 四种网络模式详解
Docker 网络是容器通信的基础,搞懂四种网络模式,容器网络就不会乱。
1. bridge 模式(默认)
这是 Docker 默认的网络模式。容器在一个虚拟的 bridge 网络里,每个容器有自己的虚拟 IP,通过 NAT 访问外部网络。
# 启动容器,默认就是 bridge
docker run -d nginx
# 查看容器 IP
docker inspect 容器ID | grep IPAddress
特点:
- 容器之间可以通过 IP 互相访问
- 外部访问需要端口映射
- 适合大多数场景
2. host 模式
容器直接用宿主机的网络,没有独立的网络栈。
docker run -d --net=host nginx
特点:
- 网络性能最好,没有 NAT 开销
- 端口直接用宿主机的,不用映射
- 多个容器不能用同一个端口
适合对性能要求高的场景。
3. none 模式
容器没有网络,完全隔离。
docker run -d --net=none nginx
特点:
- 没有任何网络
- 安全级别最高
- 适合不需要网络的离线计算任务
4. container 模式
新创建的容器和一个已存在的容器共享网络。
docker run -d --net=container:nginx容器ID redis
特点:
- 两个容器共享网络栈
- 可以用 localhost 互相访问
- 适合紧密配合的服务
5. 自定义网络
生产环境推荐用自定义网络,不用默认的 bridge:
# 创建自定义网络
docker network create mynet
# 容器加入自定义网络
docker run -d --net=mynet --name web nginx
docker run -d --net=mynet --name app php
同一个自定义网络里的容器,可以直接用容器名互相访问,不用记 IP。
总结
四种网络模式各有适用场景:
- 日常开发用默认 bridge
- 性能要求高用 host
- 安全要求高用 none
- 容器间通信密集用自定义网络
搞懂这四种模式,Docker 网络基本就够用了。
Docker Compose 实战 Docker
Docker Compose 一键部署多容器
Docker Compose 可以用一个 YAML 文件定义和运行多个 Docker 容器,开发环境部署特别方便。
1. 基本结构
version: '3'
services:
web:
image: nginx
ports:
- "80:80"
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 123456
2. 常用命令
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 停止并删除容器
docker-compose down
# 重启某个服务
docker-compose restart web
3. PHP 开发环境示例
version: '3'
services:
php:
build: .
ports:
- "8000:80"
volumes:
- ./:/var/www/html
depends_on:
- mysql
- redis
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:alpine
volumes:
mysql_data:
4. 数据卷
数据卷用来持久化数据,容器删了数据还在:
volumes:
- ./data:/var/lib/mysql
5. 网络
默认同一 Compose 里的服务在同一个网络,可以直接用服务名互相访问。比如 PHP 容器里连数据库用 mysql:3306,不用写 IP。
总结
Docker Compose 适合本地开发和测试环境。生产环境部署建议用 K8s 或者更专业的编排工具。
Docker 入门:从容器到 Compose 的实战教程 Docker
前言
Docker 现在已经是后端开发的标配工具了。很多人听说过 Docker,但不知道它到底是什么、怎么用。本文用最通俗的方式,带你从零开始掌握 Docker 的核心用法。
一、Docker 是什么
简单来说,Docker 就是把你的应用和它依赖的所有东西(代码、运行时、系统库、配置文件)打包到一个"集装箱"里,然后这个集装箱可以在任何机器上运行。
和虚拟机的区别:虚拟机是模拟一整套操作系统,Docker 容器是共享宿主机的内核,所以更轻量、启动更快。
二、核心概念
- 镜像(Image):相当于模板,只读的,用来创建容器
- 容器(Container):镜像运行起来的实例,可以创建、启动、停止、删除
- Dockerfile:用来构建镜像的脚本文件
- 仓库(Registry):存放镜像的地方,比如 Docker Hub
三、常用命令
1. 镜像操作
# 拉取镜像
docker pull nginx:latest
# 查看本地镜像
docker images
# 删除镜像
docker rmi nginx:latest
2. 容器操作
# 运行容器
docker run -d -p 80:80 --name my-nginx nginx
# 查看运行中的容器
docker ps
# 查看所有容器(包括停止的)
docker ps -a
# 停止容器
docker stop my-nginx
# 启动容器
docker start my-nginx
# 删除容器
docker rm my-nginx
# 查看容器日志
docker logs my-nginx
# 进入容器内部
docker exec -it my-nginx /bin/bash
关键参数说明:
-d:后台运行-p 80:80:端口映射,宿主机端口:容器端口--name:给容器起个名字
四、Dockerfile 实战
写一个简单的 PHP 应用镜像:
# 基于 PHP 官方镜像
FROM php:7.4-fpm
# 设置工作目录
WORKDIR /var/www/html
# 复制项目文件
COPY . .
# 安装依赖
RUN docker-php-ext-install pdo_mysql
# 暴露端口
EXPOSE 9000
# 启动命令
CMD ["php-fpm"]
构建镜像:
docker build -t my-php-app .
运行容器:
docker run -d -p 9000:9000 my-php-app
五、Docker Compose 实战
当你需要同时运行多个容器(比如 PHP + MySQL + Nginx),手动一个个启动太麻烦了。Docker Compose 就是用来编排多个容器的。
创建 docker-compose.yml 文件:
version: '3'
services:
# PHP 应用
app:
build: .
container_name: php-app
volumes:
- ./:/var/www/html
networks:
- app-network
# MySQL 数据库
db:
image: mysql:5.7
container_name: mysql-db
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: myapp
volumes:
- dbdata:/var/lib/mysql
networks:
- app-network
# Nginx 反向代理
nginx:
image: nginx:alpine
container_name: nginx-web
ports:
- "80:80"
volumes:
- ./:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- app-network
volumes:
dbdata:
networks:
app-network:
driver: bridge
启动所有服务:
docker-compose up -d
停止所有服务:
docker-compose down
六、常见问题
1. 容器启动后立刻退出
通常是因为启动命令有问题。用 docker logs 查看日志:
docker logs container_name
2. 数据持久化
容器删除后数据就没了,需要用 volumes 来持久化:
docker run -v /host/path:/container/path mysql
3. 进入容器排查问题
docker exec -it container_name /bin/bash
总结
Docker 的核心思路:
- 镜像:打包应用和依赖
- 容器:镜像的运行实例
- Dockerfile:构建镜像的脚本
- Docker Compose:多容器编排
掌握这些,你就可以用 Docker 来部署你的 Web 应用了。Docker 最大的好处就是"一次构建,到处运行",再也不会出现"我电脑上是好的"这种问题了。
Docker挂载宿主机目录后,为什么无法识别软链文件? Docker
Docker容器软链文件操作异常在将宿主机目录挂载到Docker...
Docker 挂载目录后,代码无法识别软链接,如何解决? Docker
在Docker中挂载目录后,代码无法识别软链接问题描述:在MicrosoftAzure云中,已将新添加的磁盘挂载到/mydata...
Docker Nginx 转发PHP服务时出现502错误,如何解决? Docker
Nginx转发找不到PHP服务解决方案文中提到的问题是,使用Docker配置Nginx转发PHP服务时,遇到502错误,无法找到PHP�...
Docker 中的 PHP CLI:如何在宿主机访问容器内的 PHP 命令行? Docker
通过Docker安装的PHP:如何在宿主机调用容器的PHPCLI?当你使用Docker安装PHP...