安装 Docker 可以通过官方脚本一键完成,执行以下两条命令即可:
bash
curl -fsSL https://get.docker.com -o install-docker.sh
sudo sh install-docker.sh
下载好之后如果 pull 镜像失败,可以进入 /etc/docker/daemon.json 配置镜像源。
完成之后:sudo systemctl restart docker重启生效
(作者用的是 Ubuntu,其它不同版本系统可能会有差异,有需要可以 AI search 一下)
镜像相关命令
查看镜像:docker images

输出字段说明:
- REPOSITORY:镜像的名称
- TAG :镜像的标签(如
latest) - IMAGE ID:镜像的唯一 ID
- CREATED:镜像创建时间
- SIZE:镜像的大小
搜索镜像:docker search 镜像名
拉取镜像:docker pull <image_name>:<tag>
tag 就是类似于版本,如果不指定 tag 就会默认拉取带有 latest 的镜像,一般来说一个镜像会有多个版本。
删除镜像:docker rmi IMAGE ID/REPOSITORY
注:镜像 id 或名字均可,而且镜像不能有容器实例。
镜像和容器的关系:镜像是一个文件,文件实例化运行后产生容器。如果想删除容器需要使用 docker rm 容器名/id。
容器相关指令
| 指令 | 说明 |
|---|---|
docker ps |
查看正在运行的容器 |
docker ps -a |
查看所有容器(包括已停止的) |
docker run 镜像名 |
基于镜像新建并运行容器 |
docker run -d 镜像名 |
后台运行容器(detached 模式) |
docker run -it 镜像名 /bin/bash |
交互式运行容器并进入 bash |
docker start 容器ID或名字 |
启动一个已停止的容器 |
docker stop 容器ID或名字 |
停止一个正在运行的容器 |
docker restart 容器ID或名字 |
重启容器 |
docker exec -it 容器ID或名字 bash |
在容器中启动一个新进程(进入容器) |
docker attach 容器ID或名字 |
连接到正在运行的容器(会跟随主进程) |
docker logs 容器ID或名字 |
查看容器的日志输出 |
docker rm 容器ID或名字 |
删除容器(必须先停止才能删) |
docker rm -f 容器ID或名字 |
强制删除容器(无论是否在运行) |
docker rename 旧名字 新名字 |
给容器重命名 |
docker run 常用参数
docker run -d:后台运行,不占用终端docker run --name abc:给容器命名为 abcdocker run 镜像:如果没有 pull 这个镜像,会自动拉取然后创建容器运行一个docker run -p 33061:33062:把宿主机的 33061 端口映射到容器的 33062,访问宿主机 33061 会端口转发到容器内指定端口docker run -v 宿主机路径:虚拟机路径:挂载卷,用于配置数据、日志、数据持久化docker run -e/--env Name=Value:设置环境变量docker run -it:运行的时候进入容器的终端docker run --rm:容器停止就删掉容器docker run --restart always:只要容器停止就重启(还有 unless-stopped 代替 always,类似,但是手动停止不会重启)
创建容器
创建容器:docker create 参数 镜像
创建容器但是不会运行,需要手动运行。
启停与查看
启停容器:docker stop/start
查看容器详情:docker inspect 容器id/name,可以查看容器运行时候的参数配置等。
进入容器
进入到 docker 容器的内部(简单理解为每一个容器都是单独的操作系统):
bash
docker exec -it 容器id/name /bin/bash
直接执行一条命令不进入容器:
bash
docker exec 容器名或ID ls /
Docker 镜像构建
下面以一个简单的 Gin 服务器为例,演示如何把 Go 项目构建成 Docker 镜像。
准备示例代码
这是一个简单的 Gin 服务器:
go
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/api/hello", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "hello"})
})
r.GET("/api/status", func(c *gin.Context) {
c.JSON(200, gin.H{"status": "ok"})
})
r.GET("/api/info", func(c *gin.Context) {
c.JSON(200, gin.H{"service": "gin-demo", "version": "1.0.0"})
})
r.Run(":9988")
}
编写 Dockerfile
需要编写 Dockerfile 文件,然后通过 docker build -t name . 构建成镜像。下面是对应的 Dockerfile:
dockerfile
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
COPY main.go ./
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build -o server main.go
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 9988
CMD ["./server"]
这是一个典型的双层构建,主要是为了节省存储空间。
Dockerfile 指令说明
FROM:指定系统基础,这里使用的是golang:1.25-alpine。这个可以在 Docker Hub 上面搜索,或者直接问 AI。WORKDIR:切换到指定目录。COPY:把指定文件拷贝进去。RUN:执行命令。EXPOSE:声明端口,写不写都行。CMD:指定命令,只能写一次。
查看与推送镜像
构建好的镜像直接 docker images 就可以看到。
推送到远程 Docker Hub:先登录 docker login,根据指引登录之后执行 docker push 用户名/镜像:version。
这里需要注意,构建镜像的时候最好以 dockerhub用户名/镜像名 格式命名,后续推送直接推送即可。如果只有镜像名,推送之前需要打 tag:docker tag gin-test:latest username/gin-test:latest。
这样推送完成之后就可以了,后续想 pull 下来,就直接 docker pull username/镜像:version。
Docker 网络
Docker 内部网络和宿主机的网络是隔离的,所以有时候我们需要做端口映射,来让外部可以访问容器内的服务。
通过 docker network create networkName 创建子网,在运行容器的时候可以通过 --network 指定网络。处于同一子网的容器可以通过容器的 name 互相访问,不同子网的容器不能互相访问。
举个例子:创建子网 1,启动两个容器 a、b,在 a 容器中可以直接通过 ping b 访问 b,不需要知道 b 的 IP 地址。
使用 docker network list 可以查看所有的子网。
通过 docker network rm 命令可以删除子网。
另外还可以使用 host 网络模式,直接使用宿主机的端口和 IP:
bash
docker run --network host
Docker Compose 容器编排
Docker Compose 是容器编排技术,使用 yml 文件管理多个容器。
每一个 compose 文件会自动生成一个子网,文件内启动的容器自动加入该子网。
在这之前,我们可能尝试过用命令行启动 MySQL:
bash
docker run -d \
--name my-mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
-p 3306:3306 \
--network network1
在 yml 文件中,我们可以这样写:
yaml
services:
my-sql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
ports:
- 3306:3306
volumes:
- 宿主机地址:容器地址
depends_on:
- 另一个容器
如果多个容器之间存在依赖关系,有的需要依赖于另一个容器运行,就可以使用 depends_on 指定该容器启动在指定容器之后。同时文件最上面的 services 只能出现一次,不能在一个文件里声明多个。
使用该文件也非常简单,执行 docker compose up -d 就可以了。
停止:docker compose stop
停止并删除容器:docker compose down