3、Docker入门:Docker安装、镜像与容器、Dockerfile编写、常用命令
好,咱们进入正题。Docker 这东西,说白了就是让应用「打包带走,随处运行」。我当年刚接触时也觉得玄乎,后来发现它就是个轻量级的虚拟机——但比虚拟机快得多、省得多。
这一章,我会带你从零开始,把 Docker 装好、跑起来,再亲手写个 Dockerfile。嗯,咱们一步步来。
3.1 Docker 安装:别踩这些坑
安装 Docker 其实很简单,但不同系统有点小区别。我个人习惯在 Linux 上搞,毕竟 Docker 原生就是为 Linux 设计的。
Linux(Ubuntu/CentOS)
# Ubuntu
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# CentOS
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
装完后记得启动服务:
sudo systemctl start docker
sudo systemctl enable docker
firewalld 或 iptables 规则。
macOS / Windows
直接去 Docker Desktop 官网下载安装包就行。macOS 上我推荐用 Homebrew:
brew install --cask docker
装完打开应用,等右下角小鲸鱼图标稳定下来,就说明好了。
docker version 检查是否成功。如果看到 Client 和 Server 两段信息,就对了。只有 Client 没有 Server?嗯,Docker 守护进程没启动。
3.2 镜像与容器:这俩到底啥关系?
很多人刚学 Docker 时,镜像和容器傻傻分不清。我打个比方你就懂了:
- 镜像(Image) 就像一张光盘——里面刻好了操作系统、软件、配置,是只读的。
- 容器(Container) 就像你把光盘放进光驱里运行起来——可以读写、可以交互、用完可以扔掉。
说白了,镜像就是模板,容器就是模板的实例。你想想看,Java 里类和对象的关系,是不是一个道理?
拉取镜像
docker pull nginx:latest
docker pull ubuntu:20.04
我个人习惯先拉个 alpine 镜像,它才 5MB 左右,测试网络和 Docker 环境特别方便。
查看本地镜像
docker images
运行容器
docker run -d --name my-nginx -p 8080:80 nginx:latest
这条命令的意思是:后台运行一个叫 my-nginx 的容器,把宿主机的 8080 端口映射到容器的 80 端口。
常用容器操作
| 命令 | 作用 |
|---|---|
docker ps |
查看运行中的容器 |
docker ps -a |
查看所有容器(包括已停止的) |
docker stop <容器名> |
停止容器 |
docker start <容器名> |
启动已停止的容器 |
docker rm <容器名> |
删除容器 |
docker rmi <镜像名> |
删除镜像 |
docker exec -it <容器名> bash |
进入容器内部 |
docker exec -it 进容器排查问题。比如看看日志、检查配置文件。但记住——容器里尽量别装 vim 等编辑器,保持镜像精简。用 cat 和 echo 就够了。
3.3 Dockerfile 编写:从零构建镜像
Dockerfile 就是构建镜像的「菜谱」。你写清楚步骤,Docker 按步骤一层层构建。为什么会分层?因为分层可以缓存——改了一层,其他层不用重做。
来看一个最简单的 Node.js 应用 Dockerfile:
# 1. 指定基础镜像
FROM node:18-alpine
# 2. 设置工作目录
WORKDIR /app
# 3. 复制依赖文件
COPY package*.json ./
# 4. 安装依赖
RUN npm install
# 5. 复制源码
COPY . .
# 6. 暴露端口
EXPOSE 3000
# 7. 启动命令
CMD ["node", "app.js"]
嗯,这里有个细节要注意:为什么先复制 package.json,再复制源码? 因为 package.json 不常改,而源码经常改。这样分层后,只要 package.json 没变,npm install 那层就会命中缓存,构建速度能快好几倍。
COPY . . 写在 RUN npm install 前面,结果每次改一行代码都要重新装一遍依赖。构建一次 5 分钟,整个团队都在等。后来调整了顺序,构建时间降到 10 秒。
构建镜像
docker build -t my-app:1.0 .
-t 指定镜像名和标签,最后的 . 表示 Dockerfile 在当前目录。
多阶段构建(进阶技巧)
实际项目中,我常用多阶段构建来减小镜像体积。比如 Go 应用:
# 第一阶段:编译
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o server
# 第二阶段:运行
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]
最终镜像只有几 MB,因为只包含了编译好的二进制文件和 Alpine 基础系统。编译工具链?全扔了。
3.4 常用命令速查
下面这些命令,是我日常用得最多的。你记不住没关系,收藏起来当速查表用:
| 分类 | 命令 | 说明 |
|---|---|---|
| 镜像 | docker pull <镜像名> |
拉取镜像 |
docker images |
查看本地镜像 | |
docker rmi <镜像ID> |
删除镜像 | |
| 容器 | docker run -d --name <名> <镜像> |
后台运行容器 |
docker ps -a |
查看所有容器 | |
docker logs <容器名> |
查看容器日志 | |
docker rm -f $(docker ps -aq) |
删除所有容器(慎用) | |
| 构建 | docker build -t <名> . |
构建镜像 |
docker history <镜像名> |
查看镜像构建历史 |
好,这一章就到这儿。下一章咱们聊聊 Docker Compose——当你有多个容器需要一起管理时,这东西能救你的命。