容器化入门(一)--docker入门

文摘   科技   2024-04-04 23:07   陕西  

容器化入门(一)--docker入门

1. 什么是docker:docker是一种容器技术,是一种提供容器能力的工具。容器是一个集装箱,多个集装箱(容器)可以装载到一艘鲸鱼船(OS)上, 集装箱之间彼此隔离,集装箱彼此隔离、多个集装箱可以灵活搬运组装。

2. docker的安装:在ubuntu上安装dockeer

apt install -y docker.io

3. 启动docker服务

service docker start

注意,如果是非root用户,需要将用户加入docker组

usermod -aG docker ${USER}

4. 查询docker基础信息:可以使用docker verisondocker info查询基础信息,包括版本、操作系统、当前的镜像数量等。同时,我们可以看到docker是C/S结构。

docker version
Client:
 Version:           24.0.5
 ...
 OS/Arch:           linux/amd64

Server:
 Engine:
  Version:          24.0.5
  ...
  OS/Arch:          linux/amd64
  ...
 containerd:
  Version:          1.7.2
  GitCommit:
 runc:
  Version:          1.1.7-0ubuntu1~22.04.2
  GitCommit:
 docker-init:
  Version:          0.19.0
  GitCommit:
docker info
Client:
 Version:    24.0.5
 Context:    default
 Debug Mode: false

Server:
 Containers: 3
  Running: 0
  Paused: 0
  Stopped: 3
 Images: 3
 Server Version: 24.0.5
 Storage Driver: overlay2
  Backing Filesystem: extfs
  ...
 Operating System: Ubuntu 22.04.3 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.493GiB
 ...

5. 拉取镜像:使用docker pull命令从镜像仓(默认为dockerHub)拉取别人做好的镜像

docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
Digest: sha256:c3839dd800b9eb7603340509769c43e146a74c63dca3045a8e7dc8ee07e53966
Status: Image is up to date for busybox:latest
docker.io/library/busybox:latest

6. 查询当前环境上所有的镜像:docker images

docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
alpine        latest    05455a08881e   2 months ago    7.38MB
busybox       latest    ba5dc23f65d4   10 months ago   4.26MB
hello-world   latest    d2c94e258dcb   11 months ago   13.3kB

7. 镜像删除:docker image rm 或者docker rmi

8. 创建容器:docker run

docker run busybox echo hello word
hello word

9. 查询环境上的容器:docker -ps

docker ps -a
CONTAINER ID   IMAGE         COMMAND             CREATED          STATUS                      PORTS     NAMES
5ecc1cf9336a   busybox       "echo hello word"   49 seconds ago   Exited (0) 48 seconds ago             infallible_mendel
46363adef394   alpine        "sh"                3 days ago       Exited (0) 3 days ago                 pensive_raman
71516833d612   hello-world   "/hello"            3 days ago       Exited (0) 3 days ago                 unruffled_shannon
31287dc612eb   busybox       "echo hello word"   3 days ago       Exited (0) 3 days ago                 elastic_lichterman

10. 容器删除:docker rm根据容器ID删除容器

docker rm 7151
7151

11. 理解docker的核心概念:如下一张图体现了docker的C/S结构、镜像仓Registery、镜像、容器等核心概念:

同时,可以从一个官方的示例,感受几个关键概念之间的关系:我们直接通过docker run命令运行容器时,它会先搞定镜像(本地有就用本地的、本地没有就从镜像仓下载),然后运行容器。

docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:53641cd209a4fecfc68e21a99871ce8c6920b2e7502df0a20671c6fccc73a7c6
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

12. 容器技术的再理解:容器技术是动态的容器、静态的镜像、远端的镜像仓库的三者组合

13. 进入容器的内部,感受容器是怎么一个隔离的世界:我们运行一个操作系统alpine镜像,并私用-it参数进入容器内部,执行相关命令,可以发现容器内部是一个完全隔离且完整的环境

 docker run -it alpine sh
# cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.19.1
PRETTY_NAME="Alpine Linux v3.19"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
# ps -ef
PID   USER     TIME  COMMAND
    1 root      0:00 sh
    9 root      0:00 ps -ef
# exit

14. 容器技术的核心作用:使用容器技术,将程序运行在隔离的沙盒(SandBox)之中,给应用程序加上资源的隔离。

15. 容器技术和虚拟机的对比:我们知道虚拟机也能做到资源级别的隔离,两者之间的区别可以参考下图:容器直接利用了下层计算机的硬件和操作系统,比虚拟机少了一层,这意味着更好的资源利用效率和运行效率,但是隔离成程度不如虚拟机

16. 容器的隔离实现的三大技术:

  • namespace:创建出独立的文件系统、主机名、进程号、网络等资源空间,给进程盖一间小板房
  • cgroup:实现对CPU、内存等资源的调配和控制,是小板房的天花板
  • chroot:可以更改进程的根root目录,限制文件系统的访问

17. 再说镜像和容器的关系:镜像是容器的静态只读描述文件,容器是操作系统根据镜像创建的动态隔离环境,可以说容器就是动态的镜像

18. 镜像和普通的tar、rpm等安装包的关系:镜像中不仅包括了应用程序本身、还包括了运行时的系统环境,具备更好的跨平台便携性和兼容性,是一种更高级、更便利的打包方式

19. 再说镜像:

  • 镜像的完整名称:镜像完整名称有2个部分组成,名字和标签,中间用:连接。标签可以理解为版本号。如果不指定标签,默认使用latest标签。
docker pull  alpine:3.15
docker pull ubuntu:jammy
docker pull nginx
docker pull redis
  • 镜像ID:为了方便管理镜像,每个镜像都有一个唯一的ID,跟git里的commit ID一样,它也支持短路操作,我们在根据镜像ID删除镜像时只需要提供前3-4位即可。
docker images
REPOSITORY    TAG       IMAGE ID       CREATED         SIZE
ubuntu        jammy     ca2b0f26964c   5 weeks ago     77.9MB
nginx         latest    92b11f67642b   7 weeks ago     187MB
alpine        latest    05455a08881e   2 months ago    7.38MB
redis         latest    170a1e90f843   2 months ago    138MB
alpine        3.15      32b91e3161c8   4 months ago    5.59MB
busybox       latest    ba5dc23f65d4   10 months ago   4.26MB
hello-world   latest    d2c94e258dcb   11 months ago   13.3kB
  • 镜像常用操作汇总:
命令解释
docker pull从远端仓库拉取镜像
docker images列出所有镜像
docker rmi删除镜像

20. 镜像操作补充:

  • docker run以及各类参数:基本用法是docker run 设置参数 镜像名称or 镜像ID 附件的运行命令。几个有用的参数:
参数说明
-it进入容器内部并打开shell
-d让容器以后台方式运行
--name给容器一个名字
--rm容器停止后自动删除容器
docker run -d nginx:latest
docker run -d --name red_srv redis
docker run -it --name myubuntu ca2

  • docker exec执行容器里的另一个程序:最常见的用法是使用-it参数打开一个shell从而进入容器内部。后面紧跟着的容器的ID或者容器名
docker exec -it red_srv
  • 使用docker stop停止容器:可以使用容器的ID或者容器名停止容器,多个容器空格分开即可
docker stop 47b0 c4f6
  • 容器停止后并没有彻底销毁:容器停止后,可以使用docker ps -a查询到,我们可以使用docker start继续启动运行。
docker ps -a
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS                      PORTS     NAMES
f85bee13a89f   ca2            "/bin/bash"              13 minutes ago   Exited (0) 12 minutes ago             myubuntu-d
f26ec445ef0c   ca2            "/bin/bash"              13 minutes ago   Exited (0) 13 minutes ago             myubuntu
47b07ca1098b   redis          "docker-entrypoint.s…"   14 minutes ago   Exited (0) 3 minutes ago              red_srv
c4f65e0dd250   nginx:latest   "/docker-entrypoint.…"   15 minutes ago   Exited (0) 3 minutes ago              nice_hofstadter
b39cbe3fd881   alpine         "sh"                     5 hours ago      Exited (0) 5 hours ago                elated_franklin
18da077c10ba   hello-world    "/hello"                 5 hours ago      Exited (0) 5 hours ago                tender_carver
5ecc1cf9336a   busybox        "echo hello word"        6 hours ago      Exited (0) 6 hours ago                infallible_mendel
46363adef394   alpine         "sh"                     3 days ago       Exited (0) 3 days ago                 pensive_raman
31287dc612eb   busybox        "echo hello word"        3 days ago       Exited (0) 3 days ago                 elastic_lichterman
  • 容器删除docker rm:如果确实不再需要容器,可以使用命令删除。另外,如果你想在容器停止后被自动删除,可以在运行时指定-rm参数
docker rm f85 f26 47b

21. 镜像分层:镜像打包了应用程序还有它运行所依赖的环境,包括文件系统、环境变量等。为减少容器存储、传输的消耗,容器镜像的架构实际上时分层的。可以想象一种场景,如果有1000多款基于Ubuntu的应用打包成镜像,如果不进行分层、这1000多个镜像彼此之间会有多少重复的内容。

可以按下图理解:

22. 感受镜像的分层::可以使用docker inspect查询镜像分层信息, 分层信息在FootFS中:

同时,我们的删除或者拉取镜像时也能看到分层的存在, docker会检查是否有重复的层,pull时如果本地已经存在某个层就不重复下载了,删除时如果层还被其他镜像复用就先不删除:

docker rmi nginx:latest 
Untagged: nginx:latest
Untagged: nginx@sha256:6db391d1c0cfb30588ba0bf72ea999404f2764febf0f1f196acd5867ac7efa7e
Deleted: sha256:92b11f67642b62bbb98e7e49169c346b30e20cd3c1c034d31087e46924b9312e
Deleted: sha256:d9e826dbb4b3c5770fe92638baa8c6614f210d782a5d021a123fe9fa1f92c23d
Deleted: sha256:2a75285e888884bed4d630896c86ecd71739c6e82669e21ad7a050f33c9ac48d
Deleted: sha256:32bfe3f040358ab8f9872a63d4ddefdc68f35d991ca10a812cbac5912ae9f97b
Deleted: sha256:1330486eb62ea7e96f384961b77b0fc85f5d4422e761114ef3a72e7cb89751a4
Deleted: sha256:a375372209a0f2b2c697a52cce46bc41b495bf86184ae83dd5146e20c22078eb
Deleted: sha256:450787ca55caa59d0288de9cf36fc6b77d1b208a77eb837ec3d25b385f99cafb

23. Dockerfile是什么:Dockerfile是施工图纸、是指导文档,用于指示如何创建镜像。它是一个纯文本,记录了一系列构建指令,例如选择基础镜像、拷贝文件、运行脚本等,每个指令都会生成一个层。

24. 最简单的Dockerfile实践:如下Dockerfile选择基础的镜像busybox,并添加了一条容器启动时默认执行的命令:

# Dockerfile.mybusybox
FROM busybox
CMD echo "hello world"

可以使用docker build命令创建镜像,-t可以指定名称(包括标签),-f指定Dockerfile, 同时后面还要指定构建的所在文件路径(称之为构建上下文)。

docker build -t mybosybox:qingming -f Dockerfile.mybusybox  ./
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
            Install the buildx component to build images with BuildKit:
            https://docs.docker.com/go/buildx/

Sending build context to Docker daemon    406kB
Step 1/2 : FROM busybox
 ---> ba5dc23f65d4
Step 2/2 : CMD echo "hello world"
 ---> Running in 1835a5fe24f5
Removing intermediate container 1835a5fe24f5
 ---> 859d6d96a56e
Successfully built 859d6d96a56e
Successfully tagged mybosybox:qingming

我们可以使用docker run来运行下试试:

docker run --rm mybosybox:qingming 
hello world

25. 编写正确、高效的Dockerfile:

  • FROM选择基础镜像层:如果关注镜像的安全和大小,可以使用alpine镜像;如果关注运行稳定,可以使用ubuntu、centos
  • COPY指令拷贝:可以把本机的相关文件拷贝到镜像中,但是必须是构建上下文中的路径,这个地方可以把构建上下文理解为构建时的根目录。因此,COPY /etc/hosts /tmp是一条错误指令
  • RUN命令来执行shell指令:包括更新系统、安装依赖、构建编译程序等,有时候会非常复杂,多条shell指令使用&&连接,同时RUN执行的命令过长,需要隔行时需要使用续行符\,举例:
RUN apt-get update \
  && apt-get install -y  \
     curl make unzip \
  && cd /tmp \
  && mkdir xxx \
  && curl -fSL xxx.tar.gz -o xxx.tar.gz \
  && tar xvf xxx.tar.gz \
  && cd xxx  \
  && ./config \
  && make \
  && make clean
  • 针对RUN命令的另一个技巧:这种超长的RUN命令实在不好维护,可以先将构建的shell指令存储在一个sh脚本,然后先COPY过来再执行RUN命令
COPY setup.sh  /tmp/

RUN cd /tmp && chmod +x setup.sh && ./setup.sh && rm setup.sh
  • 在Dockerfile中使用变量:可以使用ARGENV定义环境变量,两者的区别是ARG定义的环境变量只在构建镜像时可见,容器运行时不可见;而ENV定义的环境变量可以在构建时和容器运行时都可以使用
ARG IMAG_BASE="node"
ARG IMAG_TAG="alpine"

ENV PATH=$PATH:/tmp
ENV DEBUG+OFF
  • EXPOSE声明容器对外使用的端口,可以指定对外暴露的端口、以及监听的协议
EXPOSE 443
EXPOSE 53/udp
  • 尽量精简合并,否则会产生太多的导致镜像臃肿
  • docker build进一步说明:命令行docker只是一个客户端命令行,真正的构建在服务端构建,客户端将Dockerfile以及构建上下文目录打包上传。因为这样,所以COPY指令才必须使用基于构建上下文的相对路径。为了避免将构建上下文中的无效文件上传导致构建效率低下,可以通过创建.dockerignore文件的方式过滤掉不需要的文件
# dockerignore
*.swp
*.temp


编程废柴
努力Coding