前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >两小时 Docker 速成 - Getting Started

两小时 Docker 速成 - Getting Started

作者头像
szhshp
发布2022-11-02 17:28:56
6730
发布2022-11-02 17:28:56
举报
文章被收录于专栏:szhshp 的第四边境中转站

Docker: Getting Started

Why Docker?

  • 开发团队与认为, 团队之间经常互相扯皮, 主要的原因就是因为环境和配置有一定的不同
    • 比如公钥秘钥, 各类环境变量
    • 对于多个集群, 运维需要重复安装很多个环境, 最麻烦的是有一些项目会用到不同版本的环境
  • Docker 可以将一部分 代码/配置/系统/环境变量/数据 等等一系列东西全部包含进去.
    • 这个地方的 Docker Image 甚至可以把软件也一起安装了
    • 从此以后提交给运维的就是一个完全打包好的镜像
  • 对比以前的虚拟技术
    • 传统虚拟机 (e.g. Virtual Box)
      • 虚拟一套硬件
        • 其实在宿主机里面还模拟了虚拟机的内核和底层
      • 启动慢, 占用高, 步骤多
    • Docker
      • 一次构建随处运行
      • 用的是 Linux 容器虚拟化
      • 更少的抽象层: 容器内没有自己的内核, 直接使用宿主机的内核
      • 容器之间相互隔离

Concept

dockerfile + 源码 是原材料, image 是交付品, container 是运行示例

  • Docker
    • 是运行的载体以及管理引擎, 所有的操作都通过 Docker Daemon 处理
  • Image
    • 实际上就是一个 Template, 一般来说是只读的模板
    • 打包好的环境一般就是一个镜像文件
    • 通过这个镜像生成 docker 容器
  • Container
    • Image 实例化后的一个 Instance
    • 单个 Container 可以单独启动/关闭/停止/删除
    • 可以把容器看成一个简易版的 Linux 环境 + 运行在其中的应用程序
  • Repository
    • 实际上就是 Image 的内容
    • DockerHub 是最大的公开仓库
    • 国内可以使用阿里云和网易云的镜像

Installation

Install Docker Engine on Ubuntu | Docker Documentation

Ubuntu

基于 EC2, Ubuntu 20.04

代码语言:javascript
复制
sudo apt install docker.io

Cheatsheet

代码语言:javascript
复制
# 手动进入容器
sudo docker run -it [IMAGE] /bin/bash
# 一些情况下 bash 不够用, 改为 sh
sudo docker run -it [IMAGE] /bin/sh

Usage

docker --help 检查所有命令

docker run

代码语言:javascript
复制
docker run [OPTIONS] IMAGE [COMMAND] [ARG……]

docker run hello-world

# -i 交互模式运行, -t 分配一个伪输入终端, 一般一起使用
docker run -it centos
docker run -it centos --name mycentos
# 启动终端并执行自定义命令
docker run -it centos npm run dev

# 后台运行, 不弹出交互窗口也不切换
# 后台运行必须有一个持续的进程, 不然就会自动退出
docker run -d

# 打开一个新终端, 运行 tomcat
# -p 将 8080 映射到 8080
# [外部 DOCKER PORT]:[内部 IMAGE PORT]
docker run -it -p 8080:8080 tomcat

# -P 随机分配端口, 启动后可能直接看不到端口, 需要 docker ps 来查看
docker run -P tomcat
docker ps

# 携带环境变量
docker run --env VAR1=value1 --env VAR2=value2 ubuntu

默认会下载 latest 版本, 可以带上特定的 tag: docker run hello-world: latest

  1. 则检查本地是否存在这个 hello-world image, 如果有, 实例化产生 container 并运行
  2. 如果还没有, 就会去默认 registry 拉取下来, 如果可以找到, 那么拉下来, 实例化产生 container 并运行

docker image

代码语言:javascript
复制
# 列出本地所有镜像
docker images

# 列出本地所有镜像 包括中间层
docker images -a

# 列出本地所有镜像 ID
docker images -aq

docker search

代码语言:javascript
复制
# 到 dockerhub 搜索镜像关键字
docker search tomcat

docker rm/rmi

代码语言:javascript
复制
# 删除一个本地的镜像, 但是如果有容器正在使用, 将不会删除
docker rmi hello-world

# 删除多个镜像
docker rmi a:latest b:latest c d e f
docker rmi -f ${docker ps -a -q}

# 删除容器, 注意不带 i 就是删除容器, 带了 i 就是删除镜像
docker rm

# 删除多个容器
docker rm -f ${docker ps -a -q}
docker ps -a -q | xargs docker rm

docker pull

代码语言:javascript
复制
# 下载一个 image
docker pull centos

# 检查已经下载的 images
docker images

docker ps

代码语言:javascript
复制
# 列出当前 docker 所有正在运行的 container, 注意不是 image
docker ps

# 列初当前正在运行的, 以及以前历史运行过的. 这个地方可以通过状态来识别是否已经在运行.
docker ps -a

# 列出上一次运行的 container
docker ps -l

# 列出最近 50 个 container
docker ps -n 50

exit

代码语言:javascript
复制
# 退出容器, 终止容器并退出.
exit

# 不中止容器并退出
(Ctrl+P+Q)

docker start/restart/stop/kill

代码语言:javascript
复制
docker start [CONTAINER/NAME]
docker restart [CONTAINER/NAME]

# 自然关闭
docker stop [CONTAINER/NAME]

# 强制停止
docker kill [CONTAINER/NAME]

docker logs

代码语言:javascript
复制
# 查看日志, -t 包含时间戳, -f 跟随显示, --tail 默认尾部全部
docker logs -f -t --tail [CONTAINER]

docker logs -f -t --tail 3 [CONTAINER]

docker top

代码语言:javascript
复制
# 查看容器内运行的进程
docker top [CONTAINER]

docker inspect

代码语言:javascript
复制
# 查看容器内运行的细节
docker inspect[CONTAINER]

docker exec/attach

代码语言:javascript
复制
# 进入容器
docker attach [CONTAINER]

# 不进入容器就在容器中执行 ls -l /tmp, 并将结果返回宿主机
docker exec [CONTAINER] ls -l /tmp

docker cp

代码语言:javascript
复制
# 将容器内的 /tmp/test.log 拷贝到宿主机的 /root 文件夹
docker cp [CONTAINER]: /tmp/test.log /root

docker build

代码语言:javascript
复制
# 注意结尾有一个点符号

docker build -t [IMAGE_NAME]:TAG .

# -f [DOCKER_FILE] 如果不添加的话就会自动寻找文件名为 DockerFile 的文件
docker build -f [DOCKER_FILE] -t [IMAGE_NAME]:TAG .

* Other command

代码语言:javascript
复制
# 提交 container 副本令其成为一个新的 image
docker commit

# 列出镜像历史
docker history

Docker Image Architecture

镜像是一个 UnionFS (联合文件系统): 实际上是一种分层的, 高性能的, 轻量级的文件系统, 它支持对文件系统的修改作为一次提交来一层层叠加

一个 Image 可能引用了多个其他的镜像, 并且引用的镜像可以被多个 Image 引用 (类似 npm -g 的 模式)

  • 最底层是 bootfs (boot file system): 主要包含 bootloader 和 kernel
  • 上一层是 rootfs (root file system): 在 bootfs 之上, 包含的就是典型 Linux 系统中的 /dev, /proc, bin, /etc 等标准目录和文件, rootfs 就是不同操作系统的发行版
    • rootfs 相比其他系统的发布包来说会小很多, 因为只需要包含最基本的命令工具以及程序库就可以. 毕竟底层直接使用 host 的内核.

Data Volume Containers

一般来说, 容器里面产生的内容和数据在容器关闭之后会直接消失. 然后就需要将一些数据保存出来做持久化.

可以使用的方式:

  1. 直接命令添加
  2. dockerfile

docker run -v

代码语言:javascript
复制
# 如果对应的 path 没有会自动生成, 可以让 container 内部的一个 path 和外部 host 的一个 path 建立 binding
docker run -it -v [HOST_PATH]:[CONTAINER_PATH] [IMAGE]

# 添加多个 binding
docker run -it -v [HOST_PATH]:[CONTAINER_PATH] -v [HOST_PATH]:[CONTAINER_PATH] [IMAGE]

# 建立 binding 之后使用 inspect 可以从 HostConfig.Binds 里面找到
docker inspect [CONTAINER]

# 限定权限的模式, :ro 代表 read only
docker run -it -v [HOST_PATH]:[CONTAINER_PATH]:ro [IMAGE]

Volume From

代码语言:javascript
复制
# 首先创建一个容器
docker run -it --name CONTAINER_1 [IMAGE]

# 然后在容器里面创建一些文件

# 根据相同的 Image 但是根据 CONTAINER_1 进行扩展
docker run -it --volumes-from CONTAINER_1  --name CONTAINER_2 [IMAGE]

随后两个 CONTAINER 里面会有相同的文件, 在其中任何一个 CONTAINER 里面修改会影响另一个

数据卷的生命周期持续到所有 CONTAINER 的引用消失为止

比如: 此时创建 CONTAINER_3, 然后做一些修改, 然后删除 CONTAINER_1 和 CONTAINER_2, CONTAINER_3 里面依然可以看到修改

Dockerfile

Usage

使用 dockerfile 的主要的步骤:

  1. dockerfile: 编写一个 dockerfile
  2. docker build: 构建的时候引用这个 dockerfile, 生成 image
  3. docker run: image 随后可以构建 container

可以看见在多数情况下,只有构建的时候会使用到这个 dockerfile

特性:

  • 指令结构: 一段大写的单词后面带上一堆参数
  • 从上到下执行
  • 每一条指令都会新建一个镜像层, 并且对镜像进行提交
  • 执行完毕后会提交一个新的镜像层, 并且给予刚提交的镜像运行一个新的容器

Reference

  • FROM
    • 设置一个初始的镜像, 在这个镜像上扩展
    • scratch 代表最原始的镜像
  • WORKDIR
    • 设置在镜像里面的工作目录
  • ADD/COPY
    • 将宿主机目录下的文件拷贝进镜像
    • ADD 命令 比 COPY 多一个步骤, 会自动处理 URL 和解压 tar 压缩包
  • VOLUME
    • 用于数据保存和持久化
    • 会在容器里面创建新的
  • CMD
    • 格式
      • shell 格式: CMD <Command>
      • exec 格式: CMD ["executable file", "arg1", "arg2", ……]
    • Dockerfile 中多个 CMD 只会执行最后一个
      • 一般会在 dockerfile 末尾加一段 CMD 命令, 使得不带参数跑 docker run 的时候运行这段 CMD 命令
      • docker run [IMAGE] 就会默认执行最后一段 CMD
      • docker run [IMAGE] npm run dev 忽略原本 docker file 中的 CMD 并执行 npm run dev
  • ENTRYPOINT
    • 和 CMD 类似, 区别在于这个是一定执行不会有替换最后一段 CMD 的情况, 并且会追加组合对应的命令
    • ENTRYPOINT 的好处:
      • 如果在 dockerfile 中设定了 CMD ["npm", "run","dev"] 随后想要在 docker run 的时候就无法给最后一段 CMD 添加额外参数
        • CMD ["npm", "start"] + docker run [IMAGE] -iCMD ["npm", "-i","start"]
        • 这个时候必须使用 docker run 执行完整的命令或者重新 build container
      • 但是 ENTRYPOINT 可以实现
        • ENTRYPOINT ["npm", "start"] + docker run [IMAGE] -i = ENTRYPOINT ["npm", "-i","start"]
  • ONBUILD
    • 当 build 一个继承镜像的时候触发, 父镜像在被子镜像继承后触发父镜像的 onbuild
  • ENV
    • 环境变量

Example 1

一个简单的 dockerfile:

代码语言:javascript
复制
FROM centos
VOLUME ["/folder1","/folder2"]
CMD echo "Done"
CMD /bin/bash

然后 build 一个新的 image

代码语言:javascript
复制
# 注意尾部有一个点用于当前目录
docker build -f [DOCKERFILE] -t [IMAGE_NAME] . 

# 然后 docker run 跑起一个新的 container
# 新的 container 里面就会带上 folder1 和 folder2 两个目录
docker run -it [IMAGE]

# 需要注意的是, 就算这里没有使用 -v 来 bind host 的目录, docker 依然会生成一个目录用于数据持久化, 这个自动生成的逻辑只有通过 dockerfile 才会执行

Example 2

代码语言:javascript
复制
FROM centos
ENV mypath /tmp # 设置一个环境变量
WORKDIR $mypath # 设置容器内的工作目录, 设定到 /tmp

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD /bin/bash

Example 3

dockerFile1

代码语言:javascript
复制
FROM centos
ONBUILD RUN echo "this is father image" # 父镜像的 ONBUILD

假设使用上方 dockerfile 构建了一个镜像 centos1: docker build -f dockerfile1 -t centos1 .

然后编写一个新的 dockerFile:

dockerFile2

代码语言:javascript
复制
FROM centos1 # 继承刚才创建的镜像

创建一个新的镜像: docker build -f dockerfile2 -t centos2 .

这个时候就会触发父镜像里面的 ONBUILD

Troubleshotting

RUN 命令没有显示输出

加上一段参数即可

代码语言:javascript
复制
docker build -t hello-world ./ **--progress=plain --no-cache**
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Docker: Getting Started
    • Why Docker?
      • Concept
        • Installation
          • Ubuntu
        • Cheatsheet
          • Usage
            • docker run
            • docker image
            • docker search
            • docker rm/rmi
            • docker pull
            • docker ps
            • exit
            • docker start/restart/stop/kill
            • docker logs
            • docker top
            • docker inspect
            • docker exec/attach
            • docker cp
            • docker build
            • * Other command
          • Docker Image Architecture
            • Data Volume Containers
              • docker run -v
              • Volume From
            • Dockerfile
              • Usage
              • Reference
              • Example 1
              • Example 2
              • Example 3
            • Troubleshotting
              • RUN 命令没有显示输出
          相关产品与服务
          命令行工具
          腾讯云命令行工具 TCCLI 是管理腾讯云资源的统一工具。使用腾讯云命令行工具,您可以快速调用腾讯云 API 来管理您的腾讯云资源。此外,您还可以基于腾讯云的命令行工具来做自动化和脚本处理,以更多样的方式进行组合和重用。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档