Docker学习笔记(基础篇)

前言

公司绩效里面写了要学习docker,其实平时用也会用,但是没有系统的认知。

考虑到这个东西除了工作外,NAS和单子都有用到,就系统学一学吧。

下面是学习一本叫《第一本Docker书》的笔记。

另外因为成书的时间较早,需要一些外围的资料补充才能跑现在的docker。

目标1:把单子的project打包到docker

目标2:把书看完

嗯,开始吧~ 

PS1:下面的所有操作都是基于Ubuntu的,缅怀一下已经没了的Centos~

PS2:其实如果是用管理员登入的话就免去好多的sudo了~

一. Docker简介

Docker优点 

  1. 提供一个简单、轻量的建模方式
  2. 职责的逻辑分离
  3. 快速、高效的开发生命周期
  4. 鼓励使用面向服务的架构

Docker架构

  • 镜像是构建Docker世界的基石。
  • 镜像是Docker生命周期中的构建或打包阶段,而容器则是启动或执行阶段。
  • Docker借鉴了标准集装箱的概念,不同的是:集装箱运输货物,而Docker运输软件。
  • 镜像是分层的,你可以对其进行迅速的迭代。

二. Docker安装

写在最开始

下面是按照书上所说的做,最后是不行的,想要速度的请跳去这个链接
http://www.jeecms.com/hjdj/872.htm(2022-5-7亲测可行)

或各大搜索引擎搜Ubuntu安装docker 

前提条件

#查看内核版本
uname -a
#升级linux内核版本
sudo apt-get update
sudo apt-get install linux-headers-3.8.0-27-generic
linux-image-3.8.0-27-generic linux-headers-3.8.0-27
#更新Ubuntu Precise的启动加载器
sudo update-grub
#重启电脑
sudo reboot

其实书本的Ubuntu才12,我的已经不知道多少了,反正就是很高了。

所以上面的代码其实作用不大,但是为什么还要保留下来呢?

可能我觉得安装任何软件之前先确定系统版本是必要步骤吧~

go on~

#检查Device Mapper
ls  -l /sys/class/misc/device-mapper
#如果没装那么
sudo modprobe dm_mod
#添加Docker的ATP仓库
sudo sh -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"

开始安装

#检查有没有装curl
whereis curl
#没有的话就安装他
sudo apt-get -y install curl
#添加Docker仓库的GPG密钥
curl -s https://get.docker.io/gpg | sudo apt-key add -
#更新APT源
sudo apt-get update
#在Ubuntu中安装Docker
sudo apt-get install lxc-docker
#确认docker已经安装
sudo docker info

好了,按照这个书上说的已经装不了~ 哈哈哈哈哈哈哈

这个时候就去问问度娘咯~ 参考:http://www.jeecms.com/hjdj/872.htm 可以了。

总结如下:

#更新apt软件包索引并安装软件包以允许apt通过HTTPS使用存储库
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
#添加 Docker 的官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
#查看当前系统架构
dpkg --print-architecture
#根据架构选用以下对应命令执行:
#amd64:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
#armhf:
sudo add-apt-repository "deb [arch=armhf]  https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
#arm64:
sudo add-apt-repository "deb [arch=arm64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
#安装DOCKER引擎
sudo apt-get install docker-ce docker-ce-cli containerd.io
#列出可用版本
apt-cache madison docker-ce
#安装指定版本
sudo apt-get install docker-ce=<版本号> docker-ce-cli=<版本号> containerd.io
#我的就是
sudo apt-get install docker-ce=5:20.10.15~3-0~ubuntu-focal docker-ce-cli=5:20.10.15~3-0~ubuntu-focal containerd.io
#验证是否安装成功
sudo docker run hello-world

功成~ 

Docker守护进程

配置docker的访问端口,这个端口设置之后外面的人就可以通过这个端口访问了。

因为这个是没有认证的,这样就很危险了,所以需要这个叫TLS认证的东西去把把关。

当然也可以用防火墙来做~

#配置docker守护进程的网络
export DOCKER_HOST="tcp://0.0.0.0:12345"
#查看进程状态
systemctl status docker
#关闭进程
systemctl stop docker
#开启进程
systemctl start docker

docker的进程管理其实用systemctl就好了,书里面的不知道是啥,反正用不鸟~

 三. Docker入门

确保Docker已经就绪

#确保docker就绪
sudo docker info

镜像相关

书本是直接就创建容器了,但是所有容器都是基于镜像的。

所以我觉得有必要在这里补一下镜像的基础部分。

参考网址:https://www.csdn.net/tags/MtTaEgxsOTM3NDItYmxvZwO0O0OO0O0O.html

关于镜像的系统认知请看第四部分~

要点:

  • 镜像的话可以去docker hub上面找(https://hub.docker.com/)
  • 如果镜像被容器使用了,原则上来说是要先删容器再删镜像的,但是可以用-f来强制删除
#拉取镜像,默认拉最新的,可以直接run,如果没有run会自己拉镜像的
sudo docker pull ubuntu
#查看拉取了的所有镜像
sudo docker images --digests
#修改镜像库地址
vi /etc/docker/daemon.json
#输入
{
  "registry-mirrors": ["https://3laho3y3.mirror.aliyuncs.com"]
}
#删除镜像 [OPTIONS] 中 -f 表示强制删除
sudo docker rmi [OPTIONS] IMAGE [IMAGE…]
#通过短ID删除,这个代表镜像id以14f6开头的镜像,一般而言,前四位可以唯一标志,如果不可以,docker会提示的
sudo docker rmi 14f6
#通过镜像长ID删除
sudo docker rmi 14f60031763d
#通过镜像名删除
sudo docker rmi ubuntu:latest
#通过镜像的digest删除
sudo docker rmi > 
ubuntu@sha256:84c334414e2bfdcae99509a6add166bbb4fa4041dc3fa6af08046a66fed3005f
#删除所有叫redis的镜像
sudo docker rmi $(docker images –q redis)
#删除所有镜像
sudo docker rmi $(docker images –qa)

创建容器

搞了这么久终于可以创建容器了,要点有:

  • 可以使用docker run指令创建容器;
  • docker run提供了容器从创建到启动的功能;
  • -i 表示保证容器中STDIN是开启的,表示shell接受标准输入;
  • -t 表示docker为创建的容器分配一个伪tty终端;
#创建容器
sudo docker run -i -t ubuntu /bin/bash

 使用容器

因为安装的是最简的Ubuntu,所以好多包都没有默认装上

#列出所有容器
sudo docker ps -a
#列出最后一次运行的容器
sudo docker ps -l
#----- 容器内 -----
#查看主机名
hostname
#查看容器的host
cat /etc/hosts
#更新软件库
apt-get update
#安装查看网络状态的包
apt-get install -y iproute2
#查看容器接口
ip a
#退出容器
exit
#或者 ctrl + D
#----- 容器内 -----

容器命名

  • 命名规则:[a-zA-Z0-9_.-]
  • 命名必须唯一
#容器命名
sudo docker run --name test_sys -i -t ubuntu /bin/bash
#容器改名
sudo docker rename <旧容器名|旧容器id> <新容器名>
#ex:把abc的容器改名为cba
sudo docker rename abc cba

启停容器

  • 无论停止或者启动都不会进入容器内部;
  • stop向容器内发送SIGTERM信号,相当于关机;
  • kill向容器内发送SIGKILL信号,相当于断电;
#启动容器
sudo docker start <容器名|容器ID>
#重启容器
sudo docker restart <容器名|容器ID>
#停止容器
sudo docker stop <容器名|容器ID>
#如果想快速停止某个容器,那么:
sudo docker kill <容器名|容器ID>

附着到容器

上面的启动或者停止都不会进入容器,如果想再次进入那么就需要:

  • 停止的容器附着不了,需要启动了才能附着;
  • 附着后如果退出,则容器也会停止运行;
#附着到容器
sudo docker attach <容器名|容器ID>

创建守护式容器(daemonized container)

  • 上面那些都是交互式运行的容器(interactive container);
  • 守护式容器没有shell,适合运行应用程序和服务;
#创建守护式容器,并且跑一个sh,每5秒输出一个hello world
sudo docker run --name test_dc -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 5; done"

查看容器日志

  • 进入日志模式之后按 ctrl + c 退出;
#查看日志
sudo docker logs <容器名|容器ID>
#跟踪日志
sudo docker logs -f <容器名|容器ID>
#加入时间戳
sudo docker logs -ft <容器名|容器ID>
#获取最新的1000行
sudo docker logs -ft --tail 1000 <容器名|容器ID>

容器内进程

  • 使用exec指令,exec是docker1.3引入的,1.3之前看nsenter指令;
  • 相当于直接在容器内执行后面的指令了;
  • 退出交互式任务不会停止运行docker;
#查看容器内进程
sudo docker top <容器名|容器ID>
#运行容器内进程(后台任务),在etc下新建一个叫test的文件
sudo docker exec -d <容器名|容器ID> touch /etc/test
#运行容器内进程(交互式任务)
sudo docker exec -t -i <容器名|容器ID> /bin/bash

容器的自重启

--restart的值及含义:

  • no 默认策略,在容器退出时不重启容器
  • on-failure 在容器非正常退出时(退出状态非0),才会重启容器
  • on-failure:n 在容器非正常退出时重启容器,最多重启n次
  • always 在容器退出时总是重启容器(挂web服务的时候就比较有用了)
#创建一个自重启的容器
sudo docker run -d --restart=always --name <容器名> <镜像名>
#设置一个已经存在的容器自动重启
sudo docker update --restart=always <容器名|容器ID>
#当退出代码为非0时才重启
sudo docker update --restart=on-failure <容器名|容器ID>
#当退出代码为非0时才重启,并且限制重启次数为5次
sudo docker update --restart=on-failure:5 <容器名|容器ID>

获取容器详情

  • /var/lib/docker 放着所有docker的镜像、容器以及容器的配置;
  • /var/lib/docker/containers放着容器;
#通过inspect获取更多容器信息
sudo docker inspect <容器名|容器ID>
#有选择的取容器信息,比如容器运行状态
sudo docker inspect --format='{{.State.Running}}' <容器名|容器ID>

删除容器

禁术总是留到最后

#删除容器
sudo docker rm <容器名|容器ID>
#删除所有容器
sudo docker stop $(docker ps -a -q)
sudo docker rm $(docker ps -a -q)

四. Docker镜像和仓库

前言

我也不是很明白为什么先说的容器,再说的镜像~

anyway~

这里就会有对镜像的绝大部分操作了~

是什么Docker镜像

 

  • 简单来说Docker镜像就是一个只读的文件系统
  • 以一个叫联合加载技术(union mount)实现叠(套)加(娃)
  • 当需要对容器里面的只读系统进行写操作时,会复制一个副本到读写层,原来的只读系统是不会发生变法的,这个叫写时复制(copy on write)
  • 感性点说:一个容器只有一个基础镜像,基础镜像里面可以装docker,加载其他镜像(套娃)

列出镜像

  •  镜像保存在仓库中,从仓库下载下来;
  • 而仓库存在于Registry中,默认的Registry是由Docker公司运营的公共Registry服务,即Docker Hub;
  • Docker Registry的代码是开源的,可以运行自己私有的Registry服务;
#列出Docker镜像
sudo docker images
#查看docker占用系统空间
docker system df

拉取镜像

  • 书本上的pull指令默认会拉所有,但现在的pull默认只拉最新的;
  • 镜像下载下来后默认保存在:/var/lib/docker 目录下面;
  • 查看仓库中镜像的所有tags -- 浏览器打开:"${Registry地址}/${镜像名}/tags",例子:https://registry.hub.docker.com/v1/repositories/ubuntu/tags;
#默认拉取最新的镜像
sudo docker pull ubuntu
#拉取指定tag的镜像
sudo docker pull ubuntu:22.10

查找镜像

  • 可以通过docker search指令来查找所有Docker Hub上的公共可用镜像
  • 查找回来的内容包括:仓库名、镜像描述、用户评价(stars)、是否官方(Official)、是否构建(Automated,是否走了Docker Hub的构建流程)
#查找镜像
sudo docker search ubuntu

构建镜像

好了,到戏玉了

  • 构建docker的两种方法:1. docker commit指令;2. docker build指令 + Dockerfile文件;
  • 一般不推荐用docker commit来构建了;
  • 一般来说我们不是真正的创建新镜像,而是基于一个基础镜像去构建新镜像;
  • 如果想从零开始,参考:https://docs.docker.com/develop/develop-images/baseimages/;
  • Docker Hub相当于Git Hub,共有的,上了的话随便一个人都能下载下来看;
#登录Docker Hub
sudo docker login

构建镜像-commit

  • 当我们运行一个容器的时候(如果不使用卷的话),我们做的任何文件修改都会被记录与容器存储层里。而Docker提供了一个docker commit 的命令,可以将容器的存储层保存下来成为镜像。换句话说,就是在原有镜像的基础上,在叠加上容器的存储层,并构成信的镜像,以后我们运行这个新镜像的时候,就会拥有原有容器最后的文件变化。
  • 除了学习之外,docker commit还有一些特殊的应用场合,比如被入侵后保存现场等;
  • 如果在安装软件,编译构建,那会有大量的无关内容被添加进来,如果不小心清理,将会导致镜像及其臃肿。
  • commit出来的镜像是黑箱镜像,虽然docker diff或许可以得到一点线索,但是远远不到可以确保生成一致镜像的地步。
  • 任何修改的结果仅仅是在当前层进行标记,添加,修改,而不会改动上一层。
  • 其实我个人觉得commit挺好用的~ 黑盒就黑盒啊~ 让你知道那么多干嘛~ 哈哈哈哈哈哈~
#使用commit创建镜像
sudo docker commit [选项] <容器名|容器ID> [<仓库名>[:<标签>]]
#-m:提交描述,--author:作者名,Ex:
sudo docker commit -m="加入test.json文件" --author="GSSSL" ubuntu gssl/ubuntu_test_file:test
#查看提交记录
sudo docker history <容器名|容器ID>
#查看容器的修改记录
sudo docker diff <容器名|容器ID>

导入导出镜像

  • 其实镜像还能支持导入导出的,这样初期就可以绕开版本库了;
#镜像导出
sudo docker save -o <镜像导出路径及文件名> <镜像名|镜像ID>
#ex:
sudo docker save -o /home/gssl/download/test_image.tar ubuntu/latest
#镜像导入
sudo docker load --input <镜像导入路径及文件名>
#ex:
sudo docker load --input /home/gssl/download/test_image.tar

构建镜像-Dockerfile

  • Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
  • FROM 指定了 基础镜像,因此一个 DockerfileFROM 是必备的指令,并且必须是第一条指令。
  • Docker 还存在一个特殊的镜像,名为 scratch。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
  • scratch适合不以任何系统为基础,直接将可执行文件复制进镜像。
  • RUN指令的执行形式有两种:shell 格式:RUN <命令> 和 exec 格式:CMD ["可执行文件", "参数1", "参数2"]
  • 一个RUN指令就算一层镜像,Union FS 是有最大层数限制的,比如 AUFS,曾经是最大不得超过 42 层,现在是不得超过 127 层。
  • 使用 && 将各个所需命令串联起来,Dockerfile 支持 Shell 类的行尾添加 \ 的命令换行方式,以及行首 # 进行注释的格式。
  • 如果发现标准输入的文件格式是 gzipbzip2 以及 xz 的话,将会使其为上下文压缩包,直接将其展开,将里面视为上下文,并开始构建。
#----- Dockerfile -----
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 #清除缓存
#----- Dockerfile -----
#build镜像
sudo docker build [选项] <镜像名>:<TAG_ID> <上下文路径/URL/->
#ex:
sudo docker build -t test_image:1.0 .

Dockerfile 指令

  1. CMD - 用于指定一个容器启动时要运行的指令;
  2. CMD - docker run可以覆盖CMD的指令;
  3. CMD - Dockerfile中只能指定一条CMD指令,若指定多条只执行最后一条;
  4. ENTRYPOINT - 跟CMD一样,但默认docker run不会覆盖;
  5. ENTRYPOINT - 如果docker run想覆盖,那么加入--entrypoint即可
  6. RUN - 指定镜像被构建时要运行的指令;
  7. WORKDIR - 当从镜像创建一个新容器时,在容器内部设置一个工作目录,ENTRYPOINT、/、CMD都会在这个目录下执行;
  8. ENV - 在镜像构建过程中设置的环境变量;
  9. ENV - ENV <变量名> <值>,调用:$<变量名>
  10. USER - 指定该镜像以什么样的用户去运行;
  11. USER - docker run时可以用-u覆盖;
  12. VOLUME - 用来向基于镜像创建的容器添加卷;
  13. VOLUME - 关于卷有以下几个特性:
    • 卷可以再容器间共享和重用;
    • 一个容器可以不是必须和其他容器共享卷;
    • 对卷的修改是即时生效的;
    • 对卷的修改不会对更新镜像产生影响;
    • 卷会一直存在直到没有任何容器使用它;
  14. VOLUME - 可以用来测试容器和内部代码、管理日志、或者处理容器内数据库?
  15. ADD - 用来将构建环境下的文件和目录复制到镜像中,源是文件夹的话会把文件夹整个拷过去。
  16. ADD - ADD <源文件|源路径|URL> <目标文件|目标路径>
  17. ADD - ADD源文件是归档文件(就是压缩包)的话,会自动解压到目标目录,相当于-x的tar指令;
  18. ADD - 如果目标路径不存在,那么会创建这个全路径;
  19. ADD - ex: ADD xx.js /opt/app/xx.js #把xx.js写入到xx.js里面
  20. ADD - ex:ADD xx.tar /opt/app #把xx.tar解压缩到目标目录下
  21. COPY - 跟ADD类似,但COPY只关心再构建上下文复制本地文件,而不提取或解压。源是文件夹的话会把文件夹下所有内容拷过去;
  22. COPY - COPY <源文件|源路径|URL> <目标文件|目标路径>
  23. COPY - 目标目录不在Docker会自动创建目录结构,类似mkdir -p那样
  24. ONBUILD - 能为镜像添加触发器(trigger)。当一个镜像被用作其他镜像的基础镜像时,该镜像中的触发器将会被执行。
  25. ONBUILD - 一般跟在FROM之后,触发器后可以跟任何指令。
  26. ONBUILD - ONBUILD ADD ./app/src
  27. ONBUILD - 就是ONBUILD指定的操作只会在创建子镜像的时候执行一次,基于这个子镜像做的孙子镜像是不会再执行了

私有仓库

决定在构建镜像之前先把私库给搞好先;

Docker Hub上的镜像都是公家的,如果不想公开,那么就要做一个私有仓库了;

参考以下链接:

https://yeasy.gitbook.io/docker_practice/repository/registry

https://cloud.tencent.com/developer/article/1718368

docker run -d -p 5000:5000 -v /data/my_docker_registry/registry:/var/lib/registry  -v /data/my_docker_registry/config.yml:/etc/docker/registry/config.yml --name my_docker_registry registry

 

要转图形图像方面的学习了,docker就暂时到这里吧~~

其实就差docker-compose、私库部署这两块了~ 后面有时间再补吧~ 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2022-07-07 21:56  eatpockyboy  阅读(140)  评论(0编辑  收藏  举报