日常分享——Docker从入门到实践
本文最后更新于110 天前,其中的信息可能已经过时,如有错误请发送邮件到527388734@qq.com

一、引言

相信不少开发者都遇到过这样的场景:自己在本地运行完全正常的项目,打包发给别人后却无法运行,甚至出现各种难以预料的bug。这类问题往往并非代码本身有误,而是由于运行环境或依赖项的版本不一致所导致的。为了解决环境差异带来的兼容性问题,通常需要投入大量时间进行环境适配和部署调试,整个过程既耗时又耗力。

正是为了应对这一痛点,Docker应运而生。简而言之,Docker 通过将应用程序及其完整的运行环境(包括系统库、依赖项、配置文件等)一同打包,从而确保了应用在任何支持 Docker 的环境中都能以一致的方式运行。这相当于将“软件”与“运行环境”一体交付,从根本上避免了因环境差异导致的兼容性问题。

下面我们再来展开讨论一下Docker!

二、Docker是什么?

Docker 是一种容器化技术,其目标与虚拟机类似——实现环境的一致性与可移植性。例如,我们可以将一个配置好的 Ubuntu 系统打包发给其他人,并在 VMware 上运行,从而保证环境统一。然而,Docker 并非虚拟机,其本质是一种更加轻量级的进程隔离与封装技术。

它的优势在于

  • 环境一致性:一次构建,到处运行
  • 轻量级:秒级启动,资源占用小
  • 标准化:将应用和环境打包成标准单元

Docker具有三大核心概念,分别是:镜像、容器、Dockerfile。镜像的意思有点类同于一套环境模板,我们可以向这个模板里面安装需要的各种运行环境,比如Python、C++等,同时映射到嵌入式领域,它同样可以去保证Gcc工具链的一致性,从而确保了一个整体环境的一致性。而容器就是基于镜像这个模板运行起来的实体化程序,比如我基于python完成了一个websocket服务器源码,同时这个脚本在镜像环境下运行,这个进程就被叫做容器。而Dockerfile相当于就是一套规则,这个规则指的是搭建镜像环境的一套规则文件。

打一个很通俗的比喻:

  • Dockerfile = 菜谱
  • 镜像 = 做好的菜品(可以复制)
  • 容器 = 客人吃这份菜的过程

现在我们对于Docker已经有了一个初步的了解了。接下来我将介绍一下Docker的基本用法。

三、Docker常用指令

1.docker version——查看Docker版

# 基本用法
docker version

# 示例输出:
Client: Docker Engine - Community
 Version:           20.10.7
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        f0df350
 Built:             Wed Jun  2 11:56:40 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.7
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       b0f5bc3
  Built:            Wed Jun  2 11:54:50 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.6
  GitCommit:        d71fcd7d8303cbf684402823e425e9dd2e99285d
 runc:
  Version:          1.0.0-rc95
  GitCommit:        b9ee9c6314599f1b4a7f497e1f1f856fe433d3b7
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

2.docker images——查看本地镜像

# 基本用法
docker images

# 示例输出:
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
ubuntu       20.04     ba6acccedd29   2 weeks ago    72.8MB
nginx        latest    08b152afcfae   3 weeks ago    133MB
python       3.9       28a4c88cdbbf   4 weeks ago    882MB

# 常用选项:
docker images -a          # 显示所有镜像(包括中间层镜像)
docker images --digests   # 显示镜像摘要(digest)
docker images --no-trunc  # 显示完整的IMAGE ID
docker images -q          # 只显示镜像ID

# 格式化输出:
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}"

3.docker build——构建镜像

# 基本语法
docker build [OPTIONS] PATH

# 示例:
docker build -t myapp:1.0 .           # 使用当前目录的Dockerfile
docker build -f Dockerfile.dev -t dev:latest .  # 指定Dockerfile
docker build --no-cache -t myapp .    # 不使用缓存构建

# 常用选项:
-t, --tag string        # 设置镜像标签(name:tag)
-f, --file string       # 指定Dockerfile路径
--build-arg list        # 设置构建时变量
--no-cache              # 构建时不使用缓存
--pull                  # 总是尝试拉取新版本的基础镜像

4.docker pull——拉取镜像

# 基本用法
docker pull ubuntu:20.04        # 拉取指定版本
docker pull nginx               # 拉取latest标签
docker pull python:3.9-slim     # 拉取精简版

# 常用选项:
docker pull --all-tags ubuntu   # 拉取所有标签(慎用!)
docker pull --quiet ubuntu      # 安静模式,减少输出

# 从特定仓库拉取
docker pull myregistry.local:5000/myimage:1.0

5.docker push——推送镜像

docker push username/myapp:1.0

# 推送到私有仓库
docker tag myapp:1.0 myregistry.local:5000/myapp:1.0
docker push myregistry.local:5000/myapp:1.0

6.docker rmi——删除镜像

# 删除单个镜像
docker rmi ubuntu:20.04
# 删除多个镜像
docker rmi image1 image2 image3

7.docker run——运行容器

# 基本语法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 常用选项:
-d, --detach           # 后台运行
-it                    # 交互模式(-i保持STDIN打开,-t分配伪终端)
--name string          # 为容器指定名称
-p, --publish list     # 端口映射(主机端口:容器端口)
-v, --volume list      # 数据卷挂载
-e, --env list         # 设置环境变量
--rm                   # 容器退出时自动删除
--restart string       # 重启策略(no, on-failure, always, unless-stopped)
-m, --memory bytes     # 内存限制
--cpus decimal         # CPU限制

8.docker ps——查看容器

# 查看运行中的容器
docker ps

# 示例输出:
CONTAINER ID   IMAGE     COMMAND                  CREATED       STATUS       PORTS                  NAMES
a1b2c3d4e5f6   nginx     "/docker-entrypoint.…"   2 hours ago   Up 2 hours   0.0.0.0:8080->80/tcp   webserver

# 查看所有容器(包括已停止的)
docker ps -a

# 只显示容器ID
docker ps -q

# 查看最近创建的容器
docker ps -l

# 格式化输出
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}"

# 按条件过滤
docker ps -f status=running      # 只显示运行中的
docker ps -f status=exited       # 只显示已退出的
docker ps -f name=web            # 按名称过滤

9.docker stop——停止容器

# 停止单个容器
docker stop mycontainer          # 使用容器名
docker stop a1b2c3d4e5           # 使用容器ID(前几位即可)

# 停止多个容器
docker stop container1 container2

# 停止所有运行中的容器
docker stop $(docker ps -q)

# 设置停止超时时间(默认10秒)
docker stop -t 30 mycontainer    # 30秒后强制停止

10.docker restart——重启容器

# 重启容器
docker restart mycontainer

# 重启所有运行中的容器
docker restart $(docker ps -q)

# 设置重启前的等待时间
docker restart -t 10 mycontainer  # 等待10秒后重启

四、dockerfile基本语法

dockerfile 结构:指令 参数

核心指令指令包括:

1. FROM——指定基础镜像

FROM <image>[:<tag>] [AS <name>]

#示例:
FROM ubuntu:20.04 # 使用Ubuntu 20.04

2. RUN——执行命令

RUN <command>  
# 示例
RUN apt-get update && apt-get install -y \
    python3 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

RUN pip install --no-cache-dir flask
RUN ["/bin/bash", "-c", "echo Hello"]

3.COPY——复制文件

COPY [--chown=<user>:<group>] <src>... <dest>
# 示例
COPY app.py /app/                   # 复制单个文件
COPY . /app/                        # 复制当前目录所有文件

4. CMD——容器启动命令

# 语法
CMD ["executable","param1","param2"]  # exec格式(推荐)
CMD command param1 param2             # shell格式
CMD ["param1","param2"]               # 作为ENTRYPOINT参数

CMD ["python", "app.py"]              # 直接运行Python脚本
CMD ["nginx", "-g", "daemon off;"]    # Nginx前台运行
CMD python app.py                     # shell格式(不推荐)

5.WORKDIR——设置工作目录

# 语法
WORKDIR /path/to/workdir
# 示例
WORKDIR /app
RUN pwd  # 输出: /app

6.ENV——设置环境变量

# 语法
ENV <key>=<value> ...

# 示例
ENV PYTHON_VERSION=3.9.5
ENV APP_HOME=/app \
    NODE_ENV=production \
    DEBIAN_FRONTEND=noninteractive

7.EXPOSE——声明端口

# 语法
EXPOSE <port> [<port>/<protocol>...]

# 示例
EXPOSE 80          # 默认TCP
EXPOSE 80/tcp      # 明确协议
EXPOSE 80/udp
EXPOSE 8080 3000   # 多个端口

#注意
只是声明并不会自动映射,实际映射需要在docker run -p时指定

五、Docker环境搭建与验证测试

1.环境安装

#1.安装Docker引擎
sudo apt-get update
sudo apt-get install docker.io

#2.验证安装正确性
sudo docker version

#3.配置国内镜像加速器(可以拉区别人的镜像,从而快速开发)
sudo tee /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": ["https://docker.m.daocloud.io"]
}
EOF

#4.重启docker
sudo systemctl restart docker

2.第一个Hello World测试

#1.创建最简单的Dockerfile
cat > Dockerfile << 'EOF'
FROM busybox:latest                #基于远程镜像busybox环境进行开发
CMD ["echo", "Hello Docker!"]      #终端输出"Hello Docker!"
EOF

#2.构建镜像
sudo docker build -t hello-test .  #默认基于当前路径的Dockerfile进行构建
sudo docker run --rm hello-test    #运行容器

运行效果:

这个“Hello Docker!”就是基于busybox这个环境输出的,把当前的Dockerfile进行打包发送到存在Docker环境的另一个主机,从而可以实现了Hello Docker这段内容一定可以正常进行输出。

现在用的是别人的docker环境,当然我们也可以自己搭建一个Docker环境,他的重点就是在于Dockerfile的书写,从而建立起不同的运行环境!

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇