Docker基础

一、入门三板斧
  • What-Docker是什么

Docker 是世界领先的软件容器平台,所以想要搞懂 Docker 的概念我们必须先从容器开始说起。

容器是一种轻量级的、可执行的独立软件包,包含软件运行所需的所有内容:代码、运行时环境、系统工具、系统库和设置。

容器虚拟化的是操作系统而不是硬件,是内核级的虚拟化,容器之间是共享同一套操作系统资源的。虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统。因此容器的隔离级别会稍低一些。

  • Why-为什么需要用Docker、容器

Docker 的镜像提供了除内核外的完整运行时环境,确保了应用运行环境一致性,避免再出现 “代码在这台机器上正常运行, 换台机器却不能启动; 应用在测试环境没问题, 在生产环境报错” 这类问题 ——一致的运行环境

可以做到秒级、甚至毫秒级的启动时间, 大大的节约了开发、测试、部署的时间。——更快速的启动时间

避免公用的服务器,避免资源容易受到其他用户的影响。——隔离性

善于处理集中爆发的服务器使用压力, 十分适合微服务;——弹性伸缩,快速扩展

docker兼容很多平台, 可以很轻易的将在一个平台上运行的应用,迁移到另一个平台上,而不用担心运行环境的变化导致应用无法正常运行的情况。——迁移方便

使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。——持续交付和部署

  • How-如何使用Docker

需要先安装docker,然后接下来介绍docker的组件和常用命令,以及如何使用dockerfile构建自定义的镜像

二、Docker 架构

Docker 客户端-Client

Docker 服务端-Docker daemon

Docker 镜像-Image

Docker 容器-Container

Register -仓库

Docker采用的是CS架构,客户端使用docker command 命令行 与服务器进程 Docker daemon 通信。

Docker 内部组件 :镜像、容器、仓库

镜像(image):

Docker 镜像可以看作是创建容器的模板。

镜像的工作原理--分层存储

因为镜像包含操作系统完整的 根文件系统root fs,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 联合文件系统 Union FS的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。

镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。

分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。

容器(Container):

镜像和容器的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行的实体。容器可以被创建、启动、停止、删除等。

容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。前面讲过镜像使用的是分层存储,容器也是如此。

容器存储层的生存周期和容器一样,容器被删除时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失。如:容器内生成的各种日志文件, 当容器被删除时也会被删除. 正如一个对象被回收了,那他的所有成员变量占用的空间也就被释放了.

按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据 ,容器存储层要保持无状态化。**所有的文件写入操作,都应该使用数据卷(Volume) **,在这些位置的读写会跳过容器存储层,直接对宿主机(或网络存储)发生读写,其性能和稳定性更高。数据卷的生存周期独立于容器,容器被删除,数据卷也不会消失

仓库(Registry):

仓库是存放镜像的仓库,分为公有和私有两种;

最常使用的 Registry 公开服务是Docker官方的中心仓库 Docker Hub,这也是默认的 Registry,并拥有大量的官方维护的镜像;一般企业用户或者个人用户都会选择搭建属于自己的私有仓库,比如Harbor、Nexus。

Docker生态 -- 三剑客

三剑客: docker, docker-compose, docker swarm

docker: 开源项目(go), 开源版本免费, 另有商业版本(有制裁风险)

docker-compose: Docker官方开源项目(Pyhon3), 用于编排一组容器, 使用docker-compose.yml配置文件, 可以同时启动一个项目需要使用的各种容器, 如mysql, redis, nginx, jar应用. 可以像脚本一样在新服务器上快速简单地部署项目

docker swarm: Docker公司官方推出的管理docker集群的平台,现在大部分市场份额都被google的k8s占去

三、Docker实践

服务端命令

安装docker: yum install docker

启动docker 服务端: service docker start

停止docker 服务端: service docker stop

查看docker 服务端的状态: service docker status

小试牛刀--hello-world

启动docker服务端之后, 执行 docker run hello-world, 可以看到欢迎词, 显示如下

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/

客户端命令

使用docker command -h 查看docker 客户端所有的命令用法

1.在仓库中搜索镜像: docker search

Usage:  docker search [OPTIONS] TERM
Search the Docker Hub for images
Options:
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print search using a Go template
      --limit int       Max number of search results (default 25)
      --no-trunc        Don't truncate output

docker search nginx 搜索仓库中 nginx相关的镜像

2.从仓库中下载镜像: docker pull

Usage:  docker pull [OPTIONS] NAME[:TAG|@DIGEST]
Pull an image or a repository from a registry
Options:
  -a, --all-tags                Download all tagged images in the repository
      --disable-content-trust   Skip image verification (default true)

使用 docker pull[IMAGE_NAME]:[TAG]命令来下载镜像,其中 IMAGE_NAME 表示的是镜像的名称,而 TAG 是镜像的标签,也就是说我们需要通过 “镜像 + 标签” 的方式来下载镜像。

注意:

1.Docker 会尝试先从默认的镜像仓库(默认使用 Docker Hub 公共仓库)去下载,用户也可以自定义配置镜像仓库。

2.您也可以不显式地指定 TAG, 标签默认为 latest ,也就是最新版本。它是不稳定的, 在生产环境中,应显示指定具体的 TAG。

3.如果下载慢可使用国内镜像加速

docker pull centos:7

3.显示本机已下载的所有镜像: docker images

Usage:  docker images [OPTIONS] [REPOSITORY[:TAG]]
List images
Options:
  -a, --all             Show all images (default hides intermediate images)
      --digests         Show digests
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print images using a Go template
      --no-trunc        Don't truncate output
  -q, --quiet           Only show numeric IDs
  
#使用 docker images命令
docker images

REPOSITORY       TAG           IMAGE ID        CREATED            SIZE
mysql            5.7.27        383867b75fd2    10 months ago      373MB
redis            3.0.7-alpine  856249f48b0c    3 years ago        12.6MB
nginx            alpine        a624d888d69f    7 months ago       21.5MB

列表包含了 仓库名标签镜像 ID创建时间 以及 所占用的空间

其中仓库名、标签在之前的基础概念章节已经介绍过了。镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个 标签

注意:图中的镜像大小信息只是逻辑上的大小信息,因为一个镜像是由多个镜像层( layer)组成的,而相同的镜像层本地只会存储一份,所以 Docker 在下载之前,会去检测本地是否会有同样 ID 的层,如果本地已经存在了,就直接使用本地的就好了。真实情况下,占用的物理存储空间大小,可能会小于逻辑大小。

docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

可以使用docker tag 命令,为本地镜像添加一个新的标签,相当于创建一个软连接/快捷方式,镜像 ID 是一样的,只是别名不同而已。

4.删除已下载的镜像: docker rmi

Usage:  docker rmi [OPTIONS] IMAGE [IMAGE...]
Remove one or more images
Options:
  -f, --force      Force removal of the image
      --no-prune   Do not delete untagged parents

可以通过镜像名(repository:tag)或者镜像ID删除,

镜像名删除:如果镜像存在多个标签,那么删除就是删除一个标签而已;

镜像ID删除:它会先尝试删除所有指向该镜像的标签,然后在删除镜像本身。

当通过该镜像创建的容器未被全部销毁时,镜像无法直接被删除的。通过添加 -f 参数,可以强制删除镜像

5.启动容器: docker run

Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Run a command in a new container
Options: 这里列了一些常用的参数
  -d, --detach              Run container in background and print container ID 后台运行容器,并返回容器ID(唯一)
  -e, --env list            Set environment variables 注入环境变量
  -i, --interactive         Keep STDIN open even if not attached 前台交互式运行
  -l, --label list          Set meta data on a container  对容器设置标签
      --name string         Assign a name to the container 设置容器名(唯一)
      --network string      Connect a container to a network (default "default") 
      --read-only           Mount the container's root filesystem as read only 
      --rm                  Automatically remove the container when it exits
  -p, --publish list        Publish a container's port(s) to the host 宿主机端口与容器端口的映射
  -t, --tty                 Allocate a pseudo-TTY  伪终端,一般和-i搭配
  -v, --volume list         Bind mount a volume  数据卷绑定(挂载),容器的数据可持久化
      --volumes-from list   Mount volumes from the specified container(s)
  -w, --workdir string      Working directory inside the container
#利用 docker run 来创建容器, 将容器内的80端口映射到宿主机的18000端口
docker run -d --name=nginx -p 18000:80 nginx:alpine
6e5b52fae13a6669da0f87d96aef38ec02661df05e5a646eeeb00417b47ad2d5

启动容器时,如果本地没有所用的镜像则会自动下载, 一般而言执行完docker run命令后返回生成容器的ID

6.查看正在运行的容器: docker ps

展示结果的第一列是容器的ID(唯一), 最后一列NAMES是容器的名字(唯一)

Usage:  docker ps [OPTIONS]
List containers
Options:
  -a, --all             Show all containers (default shows just running)
  -f, --filter filter   Filter output based on conditions provided
      --format string   Pretty-print containers using a Go template
  -n, --last int        Show n last created containers (includes all states) (default -1)
  -l, --latest          Show the latest created container (includes all states)
      --no-trunc        Don't truncate output
  -q, --quiet           Only display numeric IDs
  -s, --size            Display total file sizes
  
CONTAINER ID     IMAGE       COMMAND      CREATED       STATUS            PORTS          NAMES
6e5b52fae13a   nginx:alpine "nginx -g 'daemon of…"   About a minute ago   Up About a minute   0.0.0.0:18000->80/tcp   nginx

可以看到nginx容器正在运行,监听宿主机的18000端口

我们可以通过访问 宿主机IP:18000 就可以访问到容器的nginx

curl http://10.93.181.200:18000/index.html

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

查看所有的容器命令: docker ps -a

容器启动失败,就会自动停止,此时就需要使用上面的命令找到已停止的容器

7.查看容器日志: docker logs

Usage:  docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output 实时跟踪显示,类似tail -f
      --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37) or relative (e.g. 42m for 42 minutes)
      
# 实时查看nginx 容器的日志
docker logs -f 6e5b52fae13a

8.容器启停: docker start/stop containerID

9.进入容器: docker attachdocker exec

docker attach containerID 可以进入当前容器运行的终端,如果从这个终端中 exit,会导致容器的停止。

所以一般都是用exec的方式

Usage:  docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Run a command in a running container
Options:
  -d, --detach               Detached mode: run command in the background
      --detach-keys string   Override the key sequence for detaching a container
  -e, --env list             Set environment variables
  -i, --interactive          Keep STDIN open even if not attached
      --privileged           Give extended privileges to the command
  -t, --tty                  Allocate a pseudo-TTY
  -u, --user string          Username or UID (format: <name|uid>[:<group|gid>])
  -w, --workdir string       Working directory inside the container
  
  # 启动一个 sh 终端进入容器(只能进入正在运行的容器)
  docker exec -it 6e5b52fae13a bash
  如果使用以上命令进入容器报错:
  OCI runtime exec failed: exec failed: container_linux.go:344: starting container process caused "exec: \"bash\": executable file not found in $PATH": unknown
  还可以使用:docker exec -it 6e5b52fae13a /bin/sh
  1. 在容器和宿主机之间复制文件/文件夹: docker cp
Usage:  docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-
        docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
Copy files/folders between a container and the local filesystem
Options:
  -a, --archive       Archive mode (copy all uid/gid information)
  -L, --follow-link   Always follow symbol link in SRC_PATH

# 1.将宿主机的文件拷贝进容器内
# 在宿主机创建foo.txt文件并拷贝到容器内
echo "bar" > foo.txt
docker cp  foo.txt nginx:/tmp

# 然后再容器内查看tmp目录
ls -ltr /tmp/
total 4
-rw-r--r--    1 root     root             4 Jul  8 11:02 foo.txt

# 2.将容器内的文件拷贝到宿主机外
# 先在容器内创建文件
echo "a" > b.txt
# 然后再在宿主机执行命令把容器拷贝出来
docker cp nginx:/tmp/b.txt ./
ls b.txt #文件存在
  1. 查看镜像/容器的详细信息:docker inspect
Usage:  docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
Options:
  -f, --format string   Format the output using the given Go template
  -s, --size            Display total file sizes if the type is container
      --type string     Return JSON for specified type

# 使用 docker inspect命令查看镜像详细信息
docker inspect nginx:alpine

# 使用 docker inspect命令查看容器详细信息
docker inspect CONTAINER_ID

12.镜像与tar文件的转换, 镜像导入docker load、导出docker save

Usage:  docker save [OPTIONS] IMAGE [IMAGE...]
Save one or more images to a tar archive (streamed to STDOUT by default)
Options:
  -o, --output string   Write to a file, instead of STDOUT

# 导出nginx镜像到当前目录的 nginx-image.tar 
docker save -o nginx-image.tar nginx:alpine
---------------------------------------------------------------------------

Usage:  docker load [OPTIONS]
Load an image from a tar archive or STDIN
Options:
  -i, --input string   Read from tar archive file, instead of STDIN
  -q, --quiet          Suppress the load output

# 导入镜像
docker load -i nginx-image.tar
四、使用DockerFile定制镜像

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了构建镜像所需的指令和说明

常用指令

FROM

指定base镜像,基于基础镜像进行构建

COPY

将文件从build context 复制到镜像

ADD

与COPY类型,从build context复制文件到镜像,不同的是如果是标准压缩文件(tar,zip,tgz,xz),那么文件会被自动解压。

ENV

设置环境变量,在Dockerfile中使用,在构建过程中有效,在image被创建和container启动后作为环境变量依旧也有效,并且可以重写覆盖。

ARG

在Dockerfile中使用,仅在build docker image的过程中(包括CMD和ENTRYPOINT)可用,在image被创建和container启动之后不可用。

RUN

在容器执行执行命令,每一个 RUN 都是启动一个容器、执行命令、然后提交存储层文件变更

WORKDIR

为RUN,CMD,ENTRYPONT,ADD或COPY 指令设置镜像中的当前工作目录

EXPOSE

指定容器容器中的进程会监听某个端口,Docker可以将该端口暴露出来

VOLUME

将文件或者目录声明为volume

CMD

容器启动时运行指定的命令,Dockerfile中可以有多个CMD指令,但是只有最后一个生效;CMD 可以被docker run 后面的参数替换

ENTRYPONT

设置容器启动时运行的命令,Dockerfile中可以有多个ENTRYPONT指令,但是只有最后一个生效;ENTRYPONT可以被docker run 后面的参数会传递给ENTRYPONT 作为参数执行(可以自行了解)。

dockerfile实战-构建简单SpringBoot应用镜像

FROM openjdk:8-jdk-alpine

# 配置同级目录下jar包名字
ENV JAR_NAME=awesomejava-0.1.jar

# 工作目录/opt,jar包会被复制为/opt/app.jar
WORKDIR /opt
COPY $JAR_NAME app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/opt/app.jar"]

使用docker build命令构建镜像

docker build --force-rm=true --no-cache=true -t awesome-java:0.1 -f Dockerfile ./

--force-rm=true 删除RUN指令的创建中间容器

-t awesome-java:0.1 指定本次构建的镜像名为 awesome-java:0.1

-f Dockerfile 指定dockerfile文件

./ build context 为当前目录,执行构建命令时,docker client 会将当前目录的所有文件发

送到服务端 daemon 的临时目录,然后按照dockerfile指令一层一层构建

镜像导出:

docker save awesome-java:0.1 | gzip > awesome-java:0.1.tar.gz

cook

  • docker镜像名字不能包含大写字母

学习指南:

Docker教程|菜鸟教程

Docker — 从入门到实践

posted @ 2020-12-22 23:34  varyuan  阅读(87)  评论(0编辑  收藏  举报