me

Docker


Docker 的基本组成

安装 Docker

官方文档:https://docs.docker.com/engine/install/centos/

配置镜像加速

在阿里云的容器服务里找到容器镜像服务,打开镜像工具,打开镜像加速器

mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker

docker 的工作原理

helloword 的运行原理

run 的运行流程

docker 的工作流程

比较

| | Docker 容器 | LXC | VM | | ---------- | ----------- | ----------- | ------------ | | 虚拟化类型 | OS 虚拟化 | OS 虚拟化 | OS 虚拟化 | | 性能 | =物理机性能 | =物理机性能 | 5%-20% 的损耗 | | 隔离性 | NS 隔离 | NS 隔离 | 强 | | QoS | Cgroup 弱 | Cgroup 弱 | 强 | | 安全性 | 中 | 差 | 强 | | GusetOS | 只支持 Linux | 只支持 Linux | 全部 | | 可迁移性 | 强 | 弱 | 强 |

镜像 (image)

镜像时一种轻量级,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含运行某个软件所需的所有内容,包括代码,环境运行时,库,环境变量等

镜像获取的方法

Docker 镜像加载的基本原理

UnionFS(联合文件系统):下载的时候一层一层的输出就是这个

Docker 镜像加载原理

分层理解

特点

docker 镜像的特点

Commit 镜像

Docker 常用命令

参考文档:https://docs.docker.com/reference/

帮助命令

镜像命令

[root@VM-12-17-centos /]# docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   3 months ago   13.3kB

# 可选项
  -a, --all     # 列出所有的镜像
  -q, --quiet   # 只显示镜像的ID
[root@VM-12-17-centos /]# docker search mysql
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                             MySQL is a widely used, open-source relation…   11997     [OK]       
mariadb                           MariaDB Server is a high performing open sou…   4595      [OK]       
mysql/mysql-server                Optimized MySQL Server Docker images. Create…   899                  [OK]

# 可选项,通过搜索来过滤
--filter = STARS = 3000  搜索出的镜像是STARS>3000的
# 下载镜像 docker pull 镜像名[:tags]
[root@VM-12-17-centos /]# docker pull mongo
Using default tag: latest # 如果不屑tag,默认就是latest
latest: Pulling from library/mongo
7b1a6ab2e44d: Pull complete # 分层下载,docker image的核心  联合文件系统
90eb44ebc60b: Pull complete 
5085b59f2efb: Pull complete 
c7499923d022: Pull complete 
019496b6c44a: Pull complete 
c0df4f407f69: Pull complete 
351daa315b6c: Pull complete 
a233e6240acc: Pull complete 
a3f57d6be64f: Pull complete 
dd1b5b345323: Pull complete 
Digest: sha256:5be752bc5f2ac4182252d0f15d74df080923aba39700905cb26d9f70f39e9702 # 签名
Status: Downloaded newer image for mongo:latest
docker.io/library/mongo:latest # 真实地址

# 下面两者等价
docker pull docker.io/library/mongo:latest
docker pull mysql

# 指定版本下载
docker pull mongo:3.1
docker rmi -f 镜像id # 删除指定的镜像
docker rmi -f 镜像id 镜像id   # 删除多个指定的镜像
docker rmi -f $(docker images -aq) # 删除全部的镜像

容器命令

下载 centos 镜像来测试docker pull centos

新建容器并启动

参数说明

# 测试,启动并进入容器
[root@VM-12-17-centos /]# docker run -it centos /bin/bash
[root@12164c10567a /]# ls
bin  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

列出所有的运行容器

退出容器

删除容器

docker rm -f $(docker ps -aq) # 删除全部的容器
docker ps -a -q|xargs docker rm   # 删除所有的容器

启动和停止容器的操作

常用的其它命令

后台启动容器

[root@VM-12-17-centos /]# docker run -d centos

# docker ps:发现centos停止了

查看日志

docker -f -t --tail 10 af1770f5884f

查看容器内部的进程命令

[root@VM-12-17-centos ~]# docker top 4fc2d1f7bf97
UID                 PID                  PPID    C         STIME               TTY                 TIME                CMD
root                12339               12319    0        15:58               pts/0               00:00:00            /bin/bash

查看容器的元数据 (重要)

[root@VM-12-17-centos ~]# docker inspect 7a447721e405

进入当前正在运行的容器

通常容器都是使用后台方式运行。需要进入容器修改一些配置

从容器中拷贝到主机上

将已经停止的容器中的内容拷贝到主机

[root@VM-12-17-centos /]# docker cp 7a447721e405:/home/test.md /home

使用-v 卷的技术可以实现自动同步

查看 cpu 状态

总结

命令原文
attachAttach to a running container当前 shel11 下 attach 连接指定运行镜像
buildBuild an image from a Dockerfile通过 Dockerfile 定制镜像
commitCreate a new image from a container changes提交当前容器为新的镜像
cpCopy files/folders from the containers filesystem to the host path从容器中拷贝指定文件或者目录到宿主机中
createCreate a new container创建一个新的容器,同 run, 但不启动容器
diffInspect changes on a container's filesys tem查看 docker 容器变化
eventsGet rea1 time events from the server从 docker 服务获取容器实时事件
execRun a command in an existing container在已存在的容器 上运行命令
exportStream the contents of a container as a tar archive导出容器的内容流作为一个 tar 归档文件[对应 import ]
historyShow the history of an image展示一个镜像形成历史
imagesList images列出系统当前镜像:
importCreate a new filesystem image from the contents of a tarba1l从 tar 包中的内容创建一个新的文件系统镜像[对应 export]
infoDisplay sys tem-wide i nformation显示系统相关信息
inspectReturn 1ow-1eve1 information on a container查看容器详细信息
killKi11 a running containerki1l 指定 docker 容器
loadLoad an image from a tar archive从一个 tar 包中加载一个镜像[对应 save]
loginRegister or Login to the docker registry server住册或者登陆一个 docker 源服务器
logoutLog out from a Docker registry server从当前 Docker registry 退出
1ogsFetch the 1ogs of a container输出当前容器日志信息
portlookup the public-facing port which is NAT-ed to PRIVATE_ PORT查看映射端口对应的容器内部源端
pausePause a11 processes within a container暂停容器
psList containers列出容器列表
pullPull an image or a repository from the docker registry server从 docker 镜像源服务器拉取指定镜像或者库镜像
pushPush an image or a repository to the docker registry server推送指定镜像或者库镜像至 docker 源服务器
restartRestart a running container重启运行的容器
rmRemove one or more : containers移除一个或者多个容器
rmiRemove one or more images移除一个或多个镜像[无容器使用该镜像才可删除,否则需删除相关容器才可继续或-f 强制删除]
runRun a command in a . new container创建一个新的容器并运行一个命令
saveSave an image to a tar archive保存一个镜像为一个 tar 包[对应 load]
searchSearch for an image on the Docker Hub在 docker hub 中搜索镜像
startStart a stopped containers启动容器
stopStop a running containers停止容器
tagTag an image into a repository给源中镜像打标签
statsDisplay a live stream of container(s) resource usage statistics查看 cpu 状态
topLookup the running processes of a container查看容器中运行的进程信息
unpauseUnpause a paused container取消暂停容器
versionShow the docker vers ion information查看 docker 版本号
waitB1ock until a container stops, then print its exit code截取容器停止时的退出状态值

案列

以装 nginx 为例

端口暴露

安装tomcat

# 官网使用命令
docker run -it --rm -p 8888:8080 tomcat:9.0

容器数据卷

Docker 容器中产生的数据,同步到本地。本地的数据也可以在容器中查看

  • windows:docker run -it -v /d/test:/home centos,路径要和 linux 的风格相同
  • linux: docker run -it -v /home/test:/home centos
  • 解释一下 linux 的吧:就是将容器中 /home目录下的文件同步到主机中 /home/test
# 挂载
"Mounts": [
    {
        "Type": "bind",
        "Source": "/d/test", # 主机内地址
        "Destination": "/home", # docker容器的地址
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
]

安装 mongoDB,官网:https://hub.docker.com/_/mongo(mongoDB 的配置文件和数据文件都在/data 下面)

# -v:数据卷挂载
# -e:设置环境配置

# 官方安装
docker run --name some-mongo -v /my/own/datadir:/data/db -d mongo

# 自己尝试连接
docker run -d -p 27017:27017 -v /g/DBMS/mongo/data:/data -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=123456 mongo
# 启动之后可以在本地使用连接

具名挂载和匿名挂载

G:\>docker volume ls
DRIVER    VOLUME NAME
local     0c65a12280af5da18c06169e98ceb7493a80082ac39cf5fc5a01263958ede773
local     test
...

使用docker volume inspect test可以查找挂载路径

[
 {
   "CreatedAt": "2022-01-22T10:27:43Z",
   "Driver": "local",
   "Labels": null,
   "Mountpoint": "/var/lib/docker/volumes/test/_data",
   "Name": "test",
   "Options": null,
   "Scope": "local"
 }
]

通过具名挂载可以很容易的找到一个卷,大多数情况下在使用具名挂载

# ro ===>readonly 只读,只能通过宿主机来操作,容器内部无法操作
# rw ===>readwrite 可读可写(默认)
# 如果设置了这些权限,容器就有限定

docker run -d -P --name nginx01 -v test:/etc/nginx:ro nginx
docker run -d -P --name nginx01 -v test:/etc/nginx:rw nginx

DockerFile

很多官方的镜像都是基础包。利用 dockerfile 自己去搭建镜像

FROM scratch
ADD centos-8-x86_64.tar.xz /
LABEL org.label-schema.schema-version="1.0"     org.label-schema.name="CentOS Base Image"     org.label-schema.vendor="CentOS"     org.label-schema.license="GPLv2"     org.label-schema.build-date="20210915"
CMD ["/bin/bash"]

DockerFile 构建

dockerFile 构建

dockerFile 的 zhiling

FROM基础镜像,构建的开始
MAINTAINER(已启用)镜像的作者,姓名 + 邮箱
LABEL代替MAINTAINER,LABEL 指令添加元数据到一个镜像。LABEL 是一个键值对 (可以有很多)
RUN构建的时刻运行的命令
ADD步骤,需要添加的镜像文件
WORKDIR镜像的工作目录
VOLUME挂载的目录
EXPOSE暴露端口 (不暴露就需要用-p)
CMD指定容器启动时候要运行的命令,只有最后一个会生效,可被 ENTRYPOINT 替代
ENTRYPOINT指定容器启动时候要运行的命令,可以追加命令
ONBUILD构建一个被继承的DockerFile就会运行ONBUILD指令,触发指令
COPY类似 ADD,将文件拷贝到镜像中
ENV构建的时候生成环境变量
SHELL指定 RUNENTRYPOINTCMD 指令的 shell

构建 centos

# 1.编写DockerFile文件
FROM centos
LABEL name="fw" email="fwqaaq@gmail.com"
ENV MYPATH = /usr/local
WORKDIR ${MYPATH} # 进入容器之后的工作目录
RUN yum -y install vim # 添加工具
RUN yum -y install net-tools # 添加工具
EXPOSE 80 # 暴露端口
CMD /bin/bash
# SHELL ["/bin/sh", "-c"] linux 默认是此命令
# 2.通过这个构建镜像
# 命令 docker build -f (构建的DockerFile文件) -t (输出的镜像名) .

[root@VM-12-17-centos Docker]# docker build -f DockerFile  -t mycentos:0.1 .

# 3.查看镜像的构建过程`docker history 镜像名`

CMDENTRYPOINT的区别

FROM centos
...
CMD "/bin/bash"

上下文

docker build -t nginx:v3 .
COPY ./package.json /app/

ONBUILD

将项目相关的指令加上 ONBUILD,这样在构建基础镜像的时候,这三行并不会被执行

FROM node:slim
RUN mkdir /app
WORKDIR /app
ONBUILD COPY ./package.json /app
ONBUILD RUN [ "npm", "install" ]
ONBUILD COPY . /app/
CMD [ "npm", "start" ]

然后各个项目的 Dockerfile 就变成了简单地:

FROM my-node

构建 Dokerfile

Dockerfile 中每一个指令都会建立一层,RUN 也不例外。所以我们尽量在一层做每一层该做的事,并且一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉

FROM debian:stretch

RUN set -x; buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

容器构建时,我们不能将它简单的使用 systemctl 或者 service 这类守护进程后台运行。

对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义

所以正确的做法是在前台执行可执行文件

CMD ["nginx", "-g", "daemon off;"]

发布镜像

发布到 Dockerhub

发布到阿里云容器

镜像的导入导出

容器的快照

区别

参考:https://jingsam.github.io/2017/08/26/docker-save-and-docker-export.html

Docker 网络

[root@VM-12-17-centos /]# docker run -d -P --name tomcat01 tomcat
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

原理

docker 网络

"HostConfig":{
   "Links": [
     "/centos01:/centos02/centos01"
   ],
}
  • 进入centos02后查看 host 文件 (cat /etc/hosts),发现--link 就是在 hosts 配置中加了172.17.0.2 centos01 2147d9e02181
  • 现在已经不建议使用**--link**
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2      centos01 2147d9e02181
172.17.0.3      5561fc170ce7

自定义网络

查看所有的 docker 网络docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
e8372c51dd7f   bridge    bridge    local
39fabbb25f72   host      host      local
dad25aaf302a   none      null      local

网络模式 (如果自己创建也会使用桥接模式)

测试

docker run -it --name centos01 --net mynet centos
docker run -it --name centos02 --net mynet centos

网络连通

docker 网络连通

将 tomcat 加入到 mynet 网络中docker network connect mynet tomcat01

"Containers": {
    "3f575a99cc32404f226d6d56cdf28be3c52c7611ae334f19297a1069b1ac9d28": {
        "Name": "tomcat01",
        "EndpointID": "6e780a6c3a680ca28c9df28b1eb14fb5fc7470e72df27d8a7444b38e1b5a0a9b",
        "MacAddress": "02:42:c0:a8:00:02",
        "IPv4Address": "192.168.0.2/16",
        "IPv6Address": ""
    }
}

Docker Compose

Compose 适用于所有环境:生产、登台、开发、测试以及 CI 工作流程。您可以在常见用例中了解有关每个案例的更多信息。

version: "3.9"  # optional since v1.27.0
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
      - logvolume01:/var/log
    links:
      - redis
  redis:
    image: redis
volumes:
  logvolume01: {}

安装

windows

Linux

# 使用国内的地址
curl -L "https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

官网的流程

Creating composetest_web_1   ... done
Creating composetest_redis_1 ... done

docker 执行的流程

yaml 配置

  • 第一层,version:编写文件格式对应的docker engine
  • 第二层。services:编写文件对应的服务 (可以无限往下写)
services:
  web:
    build: .
    ports:
      - "5000:5000"
    images:
    ...
  redis:
    image: "redis:alpine"
    ...
  ...
  • 第三层:其它配置,网络卷,全局规则
volumes:
networks:
configs:

每个服务里的编写规则

build用于服务中构建项目

command:

container_name: my-web-container指定容器名称

depends_on:表达服务之间的依赖关系 (yml 中的文件从下往上依次执行,要注意顺序)

depends_on:
  - db
  - redis

deploy:与集群相关的部署

entrypoint:默认进入容器的入口

environment:环境变量,可以设置数据库账号密码等

environment:
  - RACK_ENV=development
  - SHOW=true # 布尔值不会被编译
  - SESSION_SECRET # 从 args 获取

expose:公开端口而不将它们发布到主机 - 它们只能被链接服务访问。只能指定内部端口

expose:
  - "3000"
  - "8000"

images:指定启动容器的镜像。可以是存储库/标签镜像ID

image: ubuntu:18.04
image: a4bc65fd

networks:要加入的网络,引用顶级networkskey下的条目

services:
  some-service:
    networks:
     - some-network
     - other-network

ports:映射的端口号。如果有这个 network_mode: host`,不会启用

ports:
  - target: 80
    published: 8080
    protocol: tcp
    mode: host

restart:什么情况下重启项目

volumes可以将主机路径挂载为单个服务定义的一部分,无需在顶级 (第三层)volumes 键中定义它

volumes:
  - type: volume
    source: mydata
    target: /data
    volume:
      nocopy: true
  - type: bind
    source: ./static
    target: /opt/app/static

network 配置

networks:
  network1:
    ...
  network2:
    ...
  ...

driver:指定应为此网络使用的驱动程序

external:如果设置为 true,则指定此网络是在 Compose 之外创建的

networks:
  outside:
    external: true

name:为此网络设置自定义名称

# 不创建新网络,加入已存在的网络
networks:
  network1: true
  name: my-app-net