前言
你一定听过这句话:”在我机器上能跑,怎么到你这就崩了?”
环境配置是软件开发最头疼的问题之一。不同操作系统、不同依赖版本、不同环境变量……哪怕只是一个微小的差异,都可能导致程序运行失败。
Docker就是来彻底解决这个问题的。它把应用程序和所有依赖打包成一个”容器”,在任何机器上都能保证完全一样的运行环境。
本文会带你从零开始,亲手完成Docker的安装、容器运行和应用部署,让你5分钟上手Docker。
一、Docker是什么?
简单来说,Docker就是一个应用打包工具。
- 把你的应用 + 依赖包(Python环境、Node库、数据库等)打包成一个文件
- 这个文件可以在任何安装了Docker的机器上运行
- 运行效果完全一致,就像在虚拟机里一样
Docker vs 虚拟机
你可能觉得”这不就是虚拟机吗?” 不,它比虚拟机轻量得多:
| 特性 |
虚拟机 |
Docker容器 |
| 启动速度 |
分钟级 |
秒级 |
| 资源占用 |
几GB内存 |
几十MB内存 |
| 硬盘占用 |
几十GB |
几百MB |
| 性能开销 |
高(虚拟化整个OS) |
低(共享主机内核) |
虚拟机是”装了一个完整的操作系统”,Docker容器是”只是隔离了应用程序进程”。所以Docker启动快、占用少、性能高。
二、安装Docker
Ubuntu/Debian系统
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io
sudo docker version
|
CentOS系统
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo docker version
|
避免每次输sudo
把当前用户加入docker组,以后就不用每次都加sudo了:
1 2 3 4
| sudo usermod -aG docker $USER
newgrp docker
|
三、第一个Docker容器
运行hello-world测试Docker是否正常工作:
你会看到这样的输出:
1 2
| Hello from Docker! This message shows that your message appears to be working correctly.
|
这表示:
- Docker从远程仓库拉取了hello-world镜像
- 镜像在本地创建了容器并运行
- 容器运行成功,输出提示信息
四、核心概念:镜像和容器
镜像(Image) = 应用的打包文件(只读)
容器(Container) = 镜像运行后的实例(可读写)
类比:
- 镜像是”类(Class)”,容器是”对象(Object)”
- 镜像是”安装包”,容器是”运行中的程序”
常用镜像操作
1 2 3 4 5 6 7 8 9 10 11
| docker pull nginx
docker images
docker rmi nginx
docker search redis
|
常用容器操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| docker run -d -p 80:80 nginx
docker ps
docker ps -a
docker stop <容器ID>
docker start <容器ID>
docker rm <容器ID>
docker logs <容器ID>
docker exec -it <容器ID> /bin/bash
|
五、实战:部署一个Web应用
以部署Nginx Web服务器为例,演示完整流程。
步骤1:拉取Nginx镜像
步骤2:运行容器
1
| docker run -d -p 8080:80 --name my-nginx nginx
|
参数解释:
-d:后台运行
-p 8080:80:把容器的80端口映射到主机8080端口
--name my-nginx:给容器起个名字
步骤3:验证部署
打开浏览器访问:http://你的服务器IP:8080
你会看到Nginx的欢迎页面!
步骤4:修改网页内容
先进入容器看看:
1
| docker exec -it my-nginx /bin/bash
|
进入后你会看到类似这样的提示符:
1 2
| root@abc123:/# ls /usr/share/nginx/html/ 50x.html index.html
|
这就是Nginx的默认网页目录。修改index.html:
1 2 3
| echo "<h1>Hello Docker!</h1>" > /usr/share/nginx/html/index.html
exit
|
刷新浏览器,页面变成”Hello Docker!”了!
步骤5:用挂载卷的方式(推荐)
上面直接修改容器文件不方便,更好的方式是把主机目录挂载到容器:
1 2 3 4 5 6 7 8 9 10 11
| docker stop my-nginx docker rm my-nginx
mkdir -p ~/my-website
docker run -d -p 8080:80 --name my-nginx \ -v ~/my-website:/usr/share/nginx/html \ nginx
|
现在编辑 ~/my-website/index.html:
1
| echo "<h1>我的网站</h1><p>这是用Docker部署的</p>" > ~/my-website/index.html
|
刷新浏览器,内容立马更新!
六、实战:部署Node.js应用
假设你有一个Node.js项目,目录结构如下:
1 2 3 4
| my-app/ ├── package.json ├── index.js └── Dockerfile
|
步骤1:编写Dockerfile
在项目根目录创建Dockerfile文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| FROM node:14
WORKDIR /app
COPY package*.json ./ RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
|
步骤2:构建镜像
1 2
| cd my-app docker build -t my-node-app .
|
步骤3:运行容器
1
| docker run -d -p 3000:3000 my-node-app
|
访问 http://你的服务器IP:3000,应用就上线了!
七、常用场景速查
场景1:快速测试一个工具
想试用某个软件但不想安装?
1 2 3 4 5 6 7 8
| docker run -it redis redis-cli
docker run -it python:3.9 python
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
|
场景2:批量跑任务
有10个脚本要并行跑?开10个容器:
1 2 3
| for i in {1..10}; do docker run -d my-script done
|
场景3:开发环境隔离
不同项目需要不同Python版本?
1 2 3 4 5
| docker run -it -v $(pwd):/app python:3.7 bash
docker run -it -v $(pwd):/app python:3.11 bash
|
八、常用命令备忘录
镜像相关
1 2 3 4
| docker pull <镜像名> docker images docker rmi <镜像ID> docker build -t <名字> .
|
容器相关
1 2 3 4 5 6 7 8 9
| docker ps docker ps -a docker run <参数> <镜像> docker stop <容器ID> docker start <容器ID> docker rm <容器ID> docker logs <容器ID> docker exec -it <容器ID> /bin/bash docker cp 本地文件 容器:/路径
|
清理相关
1 2 3 4 5 6 7 8
| docker container prune
docker image prune -a
docker system prune -a
|
九、常见问题
Q1:容器启动失败怎么办?
查看日志定位问题:
Q2:如何查看容器占用的资源?
Q3:容器里安装的软件会保留吗?
不会。容器删除后,里面的修改就没了。
持久化数据的方法:
- 挂载目录:
-v 主机路径:容器路径
- 数据卷:
-v 卷名:容器路径
Q4:国内拉取镜像很慢怎么办?
配置国内镜像源,编辑 /etc/docker/daemon.json:
1 2 3 4 5 6
| { "registry-mirrors": [ "https://docker.mirrors.ustc.edu.cn", "https://hub-mirror.c.163.com" ] }
|
重启Docker:
1
| sudo systemctl restart docker
|
Q5:Docker和Kubernetes是什么关系?
- Docker是容器运行时(打包、运行容器)
- Kubernetes是容器编排平台(管理成百上千个Docker容器)
类比:
- Docker是集装箱
- Kubernetes是集装箱码头的大吊车
十、进阶:Docker Compose
如果要同时运行多个容器(比如Web + 数据库 + Redis),一个个启动太麻烦。
Docker Compose可以一次启动多个容器,只需一个配置文件。
docker-compose.yml 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| version: '3' services: web: image: nginx ports: - "8080:80" volumes: - ./website:/usr/share/nginx/html
db: image: mysql environment: MYSQL_ROOT_PASSWORD: 123456 ports: - "3306:3306"
redis: image: redis ports: - "6379:6379"
|
启动所有服务:
停止所有服务:
总结
Docker的核心就三个字:打包、分发、运行。
- 打包:把应用和依赖打包成镜像
- 分发:把镜像推送到仓库,别人拉取就能用
- 运行:在任何机器上运行容器,效果一致
掌握了Docker,你就掌握了现代应用部署的核心技能。下一步可以深入研究Docker Compose、Kubernetes、CI/CD集成等。
推荐阅读:
有问题?欢迎在评论区交流!
本文原创,转载请注明出处:洞洞博客