docker-2025-tech-blog
Docker 零基础入门2026 年还值不值得学一篇讲清镜像、容器与 ComposeDockerDocker 零基础入门2026 年还值不值得学一篇讲清镜像、容器与 Compose前言一、Docker 到底能解决什么问题二、什么是 Docker三、2026 年使用 Docker要先接受一个现实四、Docker 安装五、Docker 基本使用先分清镜像和容器1. 镜像是什么2. 容器是什么六、镜像常用命令拉取镜像搜索镜像查看本地镜像删除镜像七、容器常用命令查看运行中的容器查看所有容器启动一个容器停止 / 启动 / 重启容器删除容器八、为什么容器里服务启动了外面却访问不到1. 没做端口映射2. 程序只监听了 127.0.0.1九、数据为什么会“跟着容器一起消失”1. 绑定挂载Bind Mount2. 数据卷Volume**以上两种挂载方式,不妨试一试mysql容器添加一个数据库之后删除容器,再次创建容器,查看mysql数据库列表,分析挂载和不挂载两者在这个过程里面有什么区别**十、容器排错先看日志十一、Dockerfile把你的项目做成镜像十二、Dockerfile 里几个最重要的指令FROMWORKDIRCOPY 和 ADDRUNCMDENTRYPOINT十三、Docker 网络容器之间怎么通信1. 默认桥接网络2. 自定义桥接网络3. Host 网络模式十四、为什么多服务项目更适合 Docker Compose十五、一个典型场景Go MySQL 一起部署十六、Go 能不能直接操作 Docker十七、什么时候需要自建 Docker 私有仓库十八、初学 Docker 最容易踩的几个坑1. 端口映射做了但服务还是访问不到2. 删除容器后数据没了3. 挂载后容器里的文件不见了4. 本来想挂载文件结果变成了目录5. 容器一启动就退出前言如果你刚接触后端、运维或者服务部署大概率会遇到这样的问题本地能跑服务器跑不起来装 MySQL、Redis、Nginx 很折腾环境版本不一致换一台机器就出问题项目依赖太多部署过程又长又脆弱。Docker 的价值正是把这些问题尽量“标准化”。你可以把应用和依赖一起打包让它在不同机器上都尽可能保持一致的运行结果。很多人会问都 2025 年了还要不要学 Docker我的答案是要。Kubernetes、Podman、云原生这些概念确实越来越常见但 Docker 依然是理解容器技术、完成日常开发部署、快速搭建环境的最佳入门工具之一。一、Docker 到底能解决什么问题先看一个典型场景。你在 Windows 本地开发了一个 Web 项目准备部署到 Linux 服务器。结果上线前发现数据库版本对不上运行环境缺依赖配置文件路径不一样中间件一个个安装过程又繁琐又容易出错。而用了 Docker 之后很多服务都可以直接通过一条命令启动比如 MySQL、Redis、Nginx、Elasticsearch 等。对自己的项目来说也可以通过镜像把“代码 依赖 启动方式”一起封装起来部署时不再重复搭环境。一句话概括Docker 的核心价值不只是“装软件方便”而是“把环境差异压缩到最低”。二、什么是 DockerDocker 是一个基于容器技术的开源平台(Go语言开发而来)可以把应用及其依赖打包到一个相对独立的运行环境里。你可以这样理解镜像Image应用的“安装包模板”容器Container镜像运行后的“实例”镜像是静态的容器是动态的。一个镜像可以启动多个容器就像同一个安装包可以安装出多个实例。Docker 不是虚拟机。它和虚拟机最大的区别在于虚拟机会连操作系统一起虚拟出来比较重Docker 共享宿主机内核启动更快、资源更省。所以 Docker 特别适合本地开发环境统一服务快速部署中间件安装与管理多服务联调CI/CD 构建流程三、2026 年使用 Docker要先接受一个现实现在很多初学者卡在第一步拉不到镜像。过去不少人习惯通过国内镜像源拉取 Docker 镜像但近两年环境发生了变化很多旧教程已经不适用了。很多国内的镜像源已经无法使用了,但是不用担心,后面的教程会给大家一一到来四、Docker 安装下面以 CentOS 7 为例说明基础安装流程(环境有差异的话参考即可,可以叫ai辅助搭建环境)yum-yremove docker* 删除旧源 yuminstall-yyum-utils yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo yuminstalldocker-ce docker-ce-cli containerd.io-ysystemctl startdockersystemctlenabledocker如果yum本身也有问题先处理系统源再继续安装 Docker。(给linux内核配置一个国内源,常见是阿里云)实际部署环境大多还是 Linux因此 Docker 的学习和使用建议优先以 Linux 为主。五、Docker 基本使用先分清镜像和容器很多人学 Docker 时最容易混淆的就是镜像和容器。1. 镜像是什么镜像可以理解成“应用模板”。它里面通常包含运行环境依赖库程序文件默认启动命令比如mysql:5.7、redis:alpine、nginx:latest都是常见镜像。举一个简单的例子就是,你拉取了一个镜像就相当于你下载了一个exe文件到你得windows上,当你使用docker run的时候就相当于执行exe然后打开了客户端2. 容器是什么容器是镜像运行起来后的实例。你执行一次docker run本质上就是“基于镜像启动一个容器”。六、镜像常用命令拉取镜像dockerpull nginx(镜像名)dockerpull mysql:5.7(版本号这也可以看出来方便管理的特性)如果不写标签默认就是latest。搜索镜像dockersearch nginx查看本地镜像dockerimages删除镜像dockerrmi nginxdockerrmi mysql:5.7建议养成一个习惯先确认镜像名和标签再删除避免误删正在使用的版本。七、容器常用命令查看运行中的容器dockerps查看所有容器dockerps-a(-q 参数代表只返回容器对应id)启动一个容器dockerrun-d--namemy-nginx-p8080:80 nginx参数解释-d后台运行--name指定容器名-p 8080:80把宿主机 8080 端口映射到容器 80 端口-t代表分配一个伪终端并绑定到容器的标准输入上-i代表让容器的输入保持打开状态-e表示要设置的环境变量--restart表示容器的重启策略--privileged表示容器里面对应的用户权限停止 / 启动 / 重启容器dockerstop my-nginxdockerstart my-nginxdockerrestart my-nginx删除容器dockerrmmy-nginxdockerrm-fmy-nginx其中-f会强制删除正在运行的容器。八、为什么容器里服务启动了外面却访问不到这几乎是初学者最常见的问题之一。核心原因通常有两个1. 没做端口映射容器内部程序监听了端口不代表宿主机外部就能直接访问。你还需要用-p显式做端口映射。dockerrun-d--nameweb-p8080:8080 my-app2. 程序只监听了127.0.0.1很多程序在容器里默认只监听回环地址这样即使做了端口映射也可能访问失败。每一个容器访问的时候都会创建一个ip地址,此容器里面使用127.0.0.1对应该ip地址错误示例http.ListenAndServe(127.0.0.1:8080,nil)//这代表监听的是docker的127.0.0.1显然不是,对应容器的真实地址,跟外界的访问127.0.0.1不是一个东西更稳妥的写法http.ListenAndServe(:8080,nil)也就是让程序监听0.0.0.0。九、数据为什么会“跟着容器一起消失”因为容器本身默认是临时性的。容器删除后它可写层里的数据通常也会一起消失。所以像数据库数据、日志文件、配置文件这类内容不能只放在容器内部。这时候就要用到“目录映射”。1. 绑定挂载Bind Mount把宿主机目录直接挂到容器里dockerrun-d\--namemysql\-eMYSQL_ROOT_PASSWORD123456\-v./mysql_data:/var/lib/mysql\mysql:5.7这种方式适合日志目录配置文件本地开发联调如果挂载文件建议确认宿主机文件已经存在否则 Docker 会把它当成目录处理导致结果和预期不一致。2. 数据卷Volume数据卷由 Docker 统一管理更适合正式环境中的持久化数据。注意的是挂载数据件之前需要先创建数据件dockervolume create mysql_datadockerrun-d\--namemysql\-eMYSQL_ROOT_PASSWORD123456\-p3306:3306\-vmysql_data:/var/lib/mysql\mysql:5.7常用命令dockervolumelsdockervolume inspect mysql_datadockervolumermmysql_data如果你只是临时调试绑定挂载更直观如果是正式数据持久化数据卷通常更稳。以上两种挂载方式,不妨试一试mysql容器添加一个数据库之后删除容器,再次创建容器,查看mysql数据库列表,分析挂载和不挂载两者在这个过程里面有什么区别十、容器排错先看日志容器一启动就退出不要先怀疑 Docker先看日志。dockerlogs 容器名dockerlogs-f容器名dockerlogs--n10-f容器名 查看前10条如果日志里没有有效信息可以尝试进入容器手动执行启动命令dockerrun-it镜像名sh然后在容器里亲自跑程序看它到底缺什么、报什么错。这个方法对定位路径问题、依赖问题、权限问题很有帮助。十一、Dockerfile把你的项目做成镜像当你不只是想“运行别人的镜像”而是想把自己的项目打包成镜像时就需要写Dockerfile。下面是一个 Go 项目的常见思路# 先基于一个镜像内含Go环境和linux-alpine环境(里面编译Go程序) FROM golang:1.26-alpine AS builder ENV CGO_ENABLED0 \ GOPROXYhttps://goproxy.cn,direct # 指定工作目录(当前linux镜像里面对应的目录) WORKDIR /build # 复制当前文件 COPY . . # 配置镜像愿linux内核那里 RUN sed -i s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g /etc/apk/repositories # 编译 RUN go build -o app main.go # 第二部负责运行 因为第一步的容器内存还是比较大的 第二步的容器只放可执行文件 # 下载一个linux内核镜像 FROM alpine:latest # 工作目录 WORKDIR /app # 可以忽略知道吧,只是给容器增加相关信息 LABEL maintainerwanghao LABEL version1.0 LABEL descriptionA simple Go HTTP server # 复制可执行文件 COPY --frombuilder /build/app /app/app RUN sed -i s/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g /etc/apk/repositories RUN apk add bash # 声明容器哪个端口可以对外暴露 EXPOSE 8080 # 容器执行之后自动执行的命令 CMD [./app]这个写法体现了一个很重要的思路多阶段构建。优点是构建环境和运行环境分离最终镜像更小不需要把编译工具链一起打进生产镜像构建命令如下dockerbuild-tdemo-app(自己指定镜像名):v1.0(tag).十二、Dockerfile 里几个最重要的指令FROM指定基础镜像是所有 Dockerfile 的起点。WORKDIR设置工作目录后续命令会在这个目录下执行。COPY和ADD日常更推荐优先使用COPY。ADD功能更多(比方说压缩包直接解压)但也更容易带来隐式行为。RUN在构建镜像时执行命令比如安装依赖、创建目录、编译程序。CMD指定容器启动后的默认命令。 docker run cmd对应命令ENTRYPOINT指定容器的固定入口命令通常比CMD更强势(也就是说自己添加的命令作为ENTRYPOINT的附属命令)。可以这样理解RUN构建时执行CMD默认启动命令ENTRYPOINT固定入口命令十三、Docker 网络容器之间怎么通信Docker 安装完成后默认会有几种网络模式bridgehostnone其中最常用的是bridge。1. 默认桥接网络容器启动后会获得一个独立 IP。外部如果想访问它通常还是要配合端口映射。桥接的访问外部网络方式(容器的地址跟主机在局域网地位相当,访问外网的时候先把自己的ip转化为主机ip再访问外部网络)不过默认桥接网络有一个明显问题容器之间更适合通过名字通信不够方便。而同一个网络集群的容器之间可以使用名字通信,见下面自定义部分2. 自定义桥接网络这通常是更推荐的做法。dockernetwork create go-microservice(自定义网络名字)dockerrun-d--nameredis--networkgo-microservice redis:alpinedockerrun-d--namego-server--networkgo-microservice-p8081:8080 go-demo:1.0这样做的好处是容器之间可以直接用容器名访问不同网络之间默认隔离更适合多服务项目如果你有更细的控制需求也可以自己指定子网和网关。3. Host 网络模式Host 模式下容器直接共享宿主机网络。优点少一层网络转换某些场景性能更直接缺点也很明显端口冲突风险更高隔离性更弱Windows / macOS 上兼容性不如 Linux所以一般开发和多服务场景还是优先考虑桥接网络。十四、为什么多服务项目更适合 Docker Compose如果一个项目只有一个容器docker run还能接受。但只要你的系统里有Web 服务MySQLRedis消息队列你很快就会发现手写一堆docker run命令既难维护也不方便协作。这时就该用Docker Compose。Compose 的核心价值是用一个 YAML 文件描述多个服务一键启动和停止整套环境自动创建网络自动管理服务之间的依赖关系一个最小示例services:web:image:web:v1ports:-8081:8080restart:alwaysnetworks:-app_netweb1:image:web:v1ports:-8082:8080restart:alwaysnetworks:-app_netnetworks:app_net:driver:bridge常用命令dockercompose up -d(后台启动)dockercompose logs -f(查看日志)dockercompose stopdockercompose downdockercompose down -v(删除所有容器,网络,服务,以及数据卷(区别所在))如果你只是学习单容器先会docker run就够了但只要进入真实业务场景Compose 基本就是必备工具。十五、一个典型场景Go MySQL 一起部署比如你有一个 Go Web 服务需要依赖 MySQL那么 Compose 配置可以这样组织# 版本声明version:3services:learn_docker:image:learn_docker:v1container_name:learn_dockerports:-8080:8080#没有环境变量depends_on:-mysql# 网络要求没有network:blogrestart:alwaysmysql:image:mysql:5.7container_name:mysqlvolumes:-mysql_data:/var/lib/mysqlenvironment:-MYSQL_ROOT_PASSWORDrootrestart:always#不需要端口号因为容器之间(一个网络集群)可以互相通信network:blog# 创建一个数据卷避免手动添加volumes:mysql_data:# 建议也加到一个网络里面networks:blog:driver:bridge对应Go代码package main import ( database/sql fmt log net/http time _ github.com/go-sql-driver/mysql ) func main() { dsn : fmt.Sprintf(%s:%stcp(%s:%d)/%s?parseTimetrue, root, root, mysql, //同一个compose里面容器之间可以使用容器名进行通信 3306, mysql, ) db, err : sql.Open(mysql, dsn) if err ! nil { log.Fatalf(open mysql failed: %v, err) } defer db.Close() // 给 MySQL 一点启动时间避免容器刚起来时连接失败 for i : 1; i 20; i { err db.Ping() if err nil { log.Println(mysql connected) break } log.Printf(mysql not ready, retry %d/20: %v, i, err) time.Sleep(3 * time.Second) } if err ! nil { log.Fatalf(mysql ping failed: %v, err) } http.HandleFunc(/, func(w http.ResponseWriter, r *http.Request) { var version string err : db.QueryRow(SELECT VERSION()).Scan(version) if err ! nil { http.Error(w, query mysql failed: err.Error(), http.StatusInternalServerError) return } fmt.Fprintf(w, hello world\nmysql connected\nmysql version: %s\n, version) }) log.Println(server started at :8080) log.Fatal(http.ListenAndServe(:8080, nil)) }这个例子体现了 Compose 的几个关键能力服务编排配置挂载数据持久化服务依赖统一网络十六、Go 能不能直接操作 Docker可以。如果你要做面板系统、运维工具、自动化平台可能就需要通过代码去管理容器和镜像。Docker 官方提供了 API也有 Go SDK 可用。它通常可以完成这些操作获取镜像列表获取容器列表创建容器启动 / 停止容器设置端口映射管理网络和挂载这部分更适合已经掌握了 Docker 基础之后再继续深入。否则一上来就写 SDK反而容易把“容器原理”和“API 调用”混在一起。十七、什么时候需要自建 Docker 私有仓库在企业内网或者多台服务器统一部署时私有仓库非常有价值。它适合这些场景公司内网机器无法稳定访问公网镜像仓库团队有自己的业务镜像想统一管理镜像版本降低重复拉取外网镜像的成本最常见的做法就是运行一个registry服务dockerpull registrydockerrun-d\--nameregistry\-p5000:5000\-v/data/registry:/var/lib/registry\--restartalways\registry:latest然后给镜像重新打标签并推送dockertag alpine:latest192.168.80.185:5000/alpine:latestdockerpush192.168.80.185:5000/alpine:latest如果仓库使用的是 HTTP还需要在 Docker 配置中显式声明为可信仓库。十八、初学 Docker 最容易踩的几个坑1. 端口映射做了但服务还是访问不到优先检查程序是否监听了0.0.0.0而不是127.0.0.1。2. 删除容器后数据没了说明你没有做好数据挂载或数据卷持久化。3. 挂载后容器里的文件不见了宿主机挂载目录会覆盖容器目标路径空目录也会覆盖原内容。4. 本来想挂载文件结果变成了目录如果宿主机源路径不存在Docker 往往会自动创建目录。5. 容器一启动就退出先看docker logs不要盲猜。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2499405.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!