Docker 学习笔记(二):docker run 的参数到底在控制什么?
学 Docker 最容易被劝退的地方,不是概念,而是命令参数。
比如:
dockerrun-d--namemy-nginx-p8080:80-v./html:/usr/share/nginx/html-eTZ=Asia/Shanghai nginx:alpine第一次看到这条命令,很容易觉得:
这不就是一堆神秘参数拼起来的吗?
其实docker run可以拆成一个非常简单的句子:
用某个镜像,创建一个容器,并指定它如何运行。
这篇文章就专门拆docker run。
1. 最小命令:启动一个容器
dockerrun nginx:alpine意思是:
- 如果本地没有
nginx:alpine镜像,就先拉取; - 然后基于这个镜像创建一个容器;
- 最后启动容器。
但是这样启动有几个问题:
- 容器会占住当前终端。
- 容器没有名字,不方便管理。
- 外部访问不到容器里的端口。
- 容器里的数据默认不方便持久化。
所以才需要各种参数。
2.-d:后台运行
dockerrun-dnginx:alpine-d是 detached 的意思,也就是后台运行。
不加-d,容器日志会直接输出到当前终端。
加了-d,Docker 会返回一个容器 ID,然后容器在后台继续运行。
查看容器:
dockerps查看所有容器,包括已经停止的:
dockerps-a3.--name:给容器起名字
dockerrun-d--namemy-nginx nginx:alpine如果不给容器起名,Docker 会自动生成一个随机名字,比如:
happy_morse angry_turing学习时还好,真正排查问题时很难记。
所以建议显式写名字:
dockerlogs my-nginxdockerstop my-nginxdockerrmmy-nginx名字的价值就是:
以后所有操作都可以用这个名字定位容器。
4.-p:端口映射
最常见的命令:
dockerrun-d--namemy-nginx-p8080:80 nginx:alpine-p 8080:80的意思是:
宿主机端口:容器端口 8080:80也就是:
访问 localhost:8080 │ ▼ 转发到容器内部的 80 端口注意方向不要记反。
可以这样记:
外面写前面,里面写后面。
所以:
-p3000:3000表示宿主机3000映射到容器3000。
-p8080:80表示宿主机8080映射到容器80。
5.-v:挂载目录或数据卷
容器有一个特点:
容器删除后,容器内部新产生的数据也可能跟着消失。
比如 MongoDB 的数据、Nginx 的静态文件、上传文件,都不应该只放在容器内部。
这时要用-v。
5.1 目录挂载
dockerrun-d\--namemy-nginx\-p8080:80\-v./html:/usr/share/nginx/html\nginx:alpine意思是:
宿主机 ./html 目录 │ ▼ 挂载到容器 /usr/share/nginx/html以后你修改本机./html/index.html,容器里的 Nginx 就会读到新的文件。
5.2 命名数据卷
dockervolume create mongo-datadockerrun-d\--namemongo\-p27017:27017\-vmongo-data:/data/db\mongo:7这里的mongo-data是 Docker 管理的数据卷。
对数据库来说,通常更推荐用命名卷,而不是随便挂本地目录。
6.-e:设置环境变量
很多镜像通过环境变量初始化配置。
比如 MongoDB:
dockerrun-d\--namemongo\-p27017:27017\-eMONGO_INITDB_ROOT_USERNAME=root\-eMONGO_INITDB_ROOT_PASSWORD=123456\-vmongo-data:/data/db\mongo:7-e的意思是 environment。
可以理解成:
给容器进程注入环境变量后端项目里也常用:
-eNODE_ENV=production-eMONGO_URL=mongodb://root:123456@mongo:27017/app?authSource=admin-ePORT=30007.--rm:容器停止后自动删除
临时跑一个命令时,可以用:
dockerrun--rmnode:22-alpinenode-v意思是:
- 启动一个临时容器;
- 执行
node -v; - 执行完自动删除容器。
适合临时测试,不适合长期服务。
8.-it:进入交互式终端
dockerrun-it--rmnode:22-alpinesh这里:
-i:保持标准输入打开;-t:分配一个终端;sh:容器启动后执行 shell。
进入之后可以执行:
node-vnpm-vls如果是 Ubuntu 镜像:
dockerrun-it--rmubuntu:22.04bash9.--network:指定容器加入哪个网络
dockernetwork create app-netdockerrun-d--namemongo--networkapp-net mongo:7dockerrun-d--nameapi--networkapp-net my-api:1.0如果两个容器在同一个 Docker 网络里,它们可以用容器名互相访问。
比如后端连接 MongoDB,可以写:
mongodb://mongo:27017/app这里的mongo不是 localhost,而是容器名。
这是 Docker 网络里非常重要的一个点:
容器访问容器,不要写 localhost,要写服务名或容器名。
10. 常用生命周期命令
启动容器后,常用这些命令管理:
# 查看运行中的容器dockerps# 查看所有容器dockerps-a# 查看日志dockerlogs my-nginx# 持续查看日志dockerlogs-fmy-nginx# 停止容器dockerstop my-nginx# 启动已停止容器dockerstart my-nginx# 重启容器dockerrestart my-nginx# 删除容器dockerrmmy-nginx# 强制删除运行中的容器dockerrm-fmy-nginx11. 一条完整命令拆解
dockerrun-d\--namemongo\-p27017:27017\-eMONGO_INITDB_ROOT_USERNAME=root\-eMONGO_INITDB_ROOT_PASSWORD=123456\-vmongo-data:/data/db\--networkapp-net\mongo:7可以翻译成中文:
用
mongo:7镜像创建一个叫mongo的容器,让它后台运行,把宿主机 27017 端口映射到容器 27017 端口,设置 root 用户名密码,把数据库数据保存到mongo-data卷,并加入app-net网络。
这样一翻译,命令就不吓人了。
12. 第二篇小结
docker run的核心是:
docker run [运行参数] 镜像名 [容器内执行的命令]常见参数:
| 参数 | 作用 |
|---|---|
-d | 后台运行 |
--name | 指定容器名字 |
-p | 端口映射 |
-v | 挂载目录或数据卷 |
-e | 设置环境变量 |
--rm | 停止后自动删除 |
-it | 交互式终端 |
--network | 指定 Docker 网络 |
下一篇继续讲 Docker 网络:bridge、子网、网关、容器名访问、为什么容器里不能随便写 localhost。
参考资料
- Docker run reference: https://docs.docker.com/reference/cli/docker/container/run/
- Docker volumes: https://docs.docker.com/engine/storage/volumes/
- Docker networking overview: https://docs.docker.com/engine/network/