Docker、Podman 容器“扫盲“ 学习笔记

你拥有青春的时候,就要感受它,不要虚掷你的黄金时代,不要去倾听枯燥乏味的东西,不要设法挽留无望的失败,不要把你的生命献给无知,平庸和低俗。 ------王尔德


一、docker 原理

docker是什么?

Docker 是完整的一套容器管理系统,所以想要搞懂 Docker 的概念,我们必须先从容器开始说
起。什么是容器?

  • 容器是用来装东西的,Linux 里面的容器是用来装应用的;
  • 容器就是将软件打包成标准化单元,以用于开发、交付和部署;
  • 容器技术已经成为应用程序封装和交付的核心技术;

容器原理

容器技术的核心,由以下几个内核技术组成:

  • Cgroups (Control Groups) — 资源管理
  • SELinux — 安全 (是针对于文件系统,文件的管理措施)
  • NameSpace — 命名空间

    • 是指可以对系统资源空间进行分割隔离的技术,例如:创建一个虚拟机,在虚拟机里的所有操

作,都不会对真实机造成影响。

  + 命名空间分为六大类,可以从各个方面来对系统资源空间进行隔离;

Linux 的 NameSpace

  • UTS:主机名命名空间,作用:分割主机名,即在容器内修改主机名,不会对宿主机的系统造成影响,实现主机名的隔离;

Docker、Podman 容器“扫盲“ 学习笔记

  • NETWORK:网络命名空间,作用:分割网络,即容器内的网络配置和宿主机相互之间不受干扰的;例如在真实机器上的网卡名为eth0,IP地址为192.168.1.10/24;而在容器内的网卡名可以为ens33,ip地址为10.10.10.10/24;
  • MOUNT:挂载命名空间,作用:隔离文件系统,在容器内挂载的光盘或nfs共享目录,宿主机是无法看到里面的内

容的;例如:在linux系统上,创建一个虚拟机,在真机的/var/lib/ftp中挂载了一个光盘文件,但是在虚拟机的/var/lib/ftp中是没有光盘内容的,这就是MOUNT隔离;

  • USER:用户命名空间,作用:隔离用户,即容器内创建的用户不能用于登录宿主机,真机机里创建的用户也不能

作用于容器;

  • PID:进程命名空间,作用:为了防止容器和宿主机中的进程冲突;例如:在真实机中,有一个服务: nfs,PID为2250;在容器内,也有一个服务: chrony,PID为2250;真实机中用户,杀死(kill) PID号为2250的进程时,并不会对容器内的进程2250产生影响;而容器内的用户,杀死(kill) PID号为2250的进程时,也并不会对真实机内的进程2250产生影响;
  • IPC:信号向量命名空间,作用:通常和PID一起使用;用户杀死一个进程时,实际上是向进程发送一个信号(IPC),进程接收到这个信号后会执行对应的操作;

docker 的特性

docker 的优缺点

  • 优点:相比于传统的虚拟化技术,容器更加简洁高效,传统虚拟机需要给每个 VM 安装操作系统,容器使用的共享公共库和程序
  • 缺点:容器的隔离性没有虚拟机强共用Linux内核,安全性有先天缺陷.

docker 的特点

  • docker 与传统虚拟化的对比:

    • 虚拟化:例如:虚拟机的使用,每一个虚拟机都要安装独立的操作系统;将一台服务器转变为多台服务器的物理硬件的抽象。系统管理程序允许多个VM在单台计算机上运行。每个VM包含操作系统,应用程序,必要的二进制文件和库的完整副本-占用数十GB。VM也可能启动缓慢。
    • 容器:不需要安装独立的操作系统,只有一个Docker进程,和宿主机共享操作系统;容器没有操作系统,启动容器就跟开启一个进程一样,简单高效;是应用程序层的抽象,将代码和依赖项打包在一起。多个容器可以在同一台计算机上运行,​​并与其他容器共享OS内核,每个容器在用户空间中作为隔离的进程运行。容器占用的空间少于VM(容器映像的大小通常为几十MB),可以处理更多的应用程序,并且需要的VM和操作系统更少。
  • 运行区别( 容器的高效性)

    • 启动虚拟机中的应用程序,需要先启动虚拟机的操作系统,然后再启动应用程序
    • 启动容器内的应用程序,直接启动应用程序即可Docker、Podman 容器“扫盲“ 学习笔记

二、docker 安装部署

docker安装

安装条件

  • 需要64位操作系统,至少 RHEL6.5 以上的版本,强烈推荐 RHEL7
  • docker安装时,内核要求在3.0以上,RHEL7的内核默认在3.0以上,不满足可以单独升级系统内核。
查看linux系统的内核版本,【uname -r】也可以
Docker、Podman 容器“扫盲“ 学习笔记
  • 关闭防火墙 (不是必须):firewalld【RHEL7使用】,Iptables【RHEL6使用】,Docker安装时,会自动的接管防火墙,并向防火墙里添加配置,如果防火墙存在,会产生冲突。

源配置

  • 配置 yum 源
  • 在物理机的 http 目录下创建文件夹 extras: mkdir /var/www/html/extras
  • 把光盘挂到这个目录下 : mount -t iso9660 -o ro,loop RHEL70OSP-extras.iso /var/www/html/extras

docker安装

  • 卸载防火墙 yum remove -y firewalld-*
  • 安装软件包 yum install docker
  • 开启路由转发 /etc/sysctl.conf net.ipv4.ip_forward=1 使用sysctl -p 让配置立刻生效(否则需要重新虚拟机)docker是通过虚拟交互机来进行通讯的,需要开启路由转发的功能。

Docker、Podman 容器“扫盲“ 学习笔记

  • 软件的 BUG : iptables -nL FORWARD 版本 大于 1.12 时会设置 FORWARD 的默认规则,被设置为 DROP,对于有些docker的版本中,FORWARD链的规则被设置成了DROP,会造成容器和宿主机之间无法通讯。

Docker、Podman 容器“扫盲“ 学习笔记
解决办法:

  • 修改 /lib/systemd/system/docker.server

Docker、Podman 容器“扫盲“ 学习笔记

  • 重载配置文件,重启服务 systemctl daemon-reload systemctl restart docker
[root@liruilong ~]# systemctl daemon-reload
[root@liruilong ~]# systemctl restart docker

三、获取镜像

镜像、容器、仓库

什么是镜像

镜像是启动容器的核心,在Docker容器是基于镜像启动的,镜像采用分层设计,使用 COW 技术

  • 容器本身是没有操作系统,和宿主机共用一个操作系统;
  • 容器是docker(容器的管理工具)使用镜像文件来启动的;
  • 镜像是启动容器的模板,镜像中存放的是应用程序(服务软件),例如: 有一个http的镜像文件,在这个镜像中就存放的是http的所有文件和变量
  • 用户使用镜像启动容器时,会生成一个独立于镜像的容器层,并不会对镜像层产生任何影响;
  • 而且容器采用了cow(写时复制)的技术,用户可以使用一个镜像文件创建多个容器,互不干扰;
  • 镜像采用分层技术:用户可以根据自己的需求来制作镜像,例如:在镜像的第一层定义应用程序的变量,在镜像的第二层修改配置文件,在镜像的第三层进行应用软件的部署;分层做好镜像后,用户使用镜像启动容器时,可以选择根据镜像哪一层来启动,类似快照还原;

Docker、Podman 容器“扫盲“ 学习笔记

容器使用镜像启动

Docker、Podman 容器“扫盲“ 学习笔记

镜像是怎么来的?

镜像可以从官方镜像仓库下载,也可以自己制作

Docker、Podman 容器“扫盲“ 学习笔记

  • REPOSITORY 镜像名称

  • TAG 镜像标签

  • IMAGE ID 镜像ID号

  • CREATED 镜像创建时间

  • SIZE 镜像大小

获取镜像

查找镜像 :docker search 关键字 docker search jdk

Docker、Podman 容器“扫盲“ 学习笔记

  • INDEX 索引名称,即网站域名

  • NAME 镜像的名称

  • DESCRIPTION 镜像的描述信息

  • STARS 镜像被下载的次数

  • OFFICIAL 是否是docker官方开发的

  • AUTOMATED 是否自动构建镜像

下载镜像 docker pull 镜像名称:标签 : docker pull docker.io/busybox

镜像的备份与恢复

备份镜像 (导出镜像): docker save 镜像名称:镜像标签 -o 备份文件夹(tar格式)
  • 镜像busybox,需要指定名字和标签,导出到/root目录下,名称为busybox.tar
[root@kube-node1 ~]$ docker save docker.io/busybox:latest -o /root/busybox.tar
  • 拷贝备份镜像到其他机器上
[root@kube-node1 ~]$ scp /root/busybox.tar 192.168.1.22:/root/
恢复镜像(导入镜像) docker load -i 备份文件名称
docker load -i busybox.tar

四、第一个容器

运行容器

docker run 命令

docker run -参数 镜像名称:镜像标签 启动命令
  • 镜像名称:镜像标签这种形式,可以指定唯一的镜像,防止镜像名相同,内容不同的情况,latest为默认标签,创建镜像时,不指定标签,则为此默认标签

+ run = 创建 + 启动 + 进入docker run 命令: 运行过程中,会先根据镜像创建容器,然后会启动容器,最后进入容器

  • 帮助文档:查看 run 的参数: docker help run man docker-run
  • 参数: -i 交互式, -t终端, -d 后台运行, --name 容器名字 :docker run -it docker.io/centos:lasest /bin/bash(#/bin/bash 容器内的命令,容器内存在,才可以使用)

Docker、Podman 容器“扫盲“ 学习笔记

五、docker 镜像管理

镜像管理命令

  • 查看镜像: docker images
  • 查找镜像 docker search
  • 删除镜像 docker rmi 镜像名称:镜像标签 && docker image rm fd1c5f7b6816
  • 下载镜像 docker pull 镜像名称: 镜像标签
  • 上传镜像 docker push 要上传的镜像名称: 镜像标签
  • 备份镜像 docker save 镜像名称: 镜像标签 -o 备份文件名称
  • 恢复镜像 docker load -i 备份文件名称
  • 查看镜像的制作历史 docker history 镜像名称: 镜像标签
  • 查看镜像的信息 docker inspect 镜像名称: 镜像标签
  • 镜像的新名称和标签 docker tag 镜像名称: 镜像标签 新镜像名称: 新的标签

Docker、Podman 容器“扫盲“ 学习笔记

六、docker 容器管理

常用容器管理命令

  • 启动容器 docker run -参数 镜像名称:镜像标签 启动命令
  • 查看容器 docker ps [ -a 所有容器id ] [ -q 只显示容器 id ]
  • 删除容器 docker rm 容器id
  • 容器管理启动 docker start 容器id
  • 容器管理停止 docker stop 容器id
  • 容器管理重启 docker restart 容器id
  • 查看容器进程 docker top 容器id
  • 查看容器信息 docker inspect 容器id
  • 连接容器启动进程 docker attach 容器id

    • attach 以上帝进程的身份,进入容器内部,使用attach进入容器,是上帝进程的身份进入容器的,当执行exit退出容器时,会结束整个容器,查看进程树,systemd就是上帝进程,即:系统服务的最初进程,所有的进程都是在上帝进程下创建的;当systemd进程被结束时,整个系统也就会崩溃通常用于在测试时,查看报错信息;

Docker、Podman 容器“扫盲“ 学习笔记

  • 连接容器,启动新进程 docker exec -it 容器id 命令

    • 在对容器的使用过程中,都是使用exec,新开一个进程的方式进入容器,进行编辑的;而attach 往往应用于调试,终端输出的情况;

七,自定义镜像

commit 自定义镜像

自定义镜像原理 :镜像采用分层设计:1,创建读写层 2,修改配置 3,重新打包
Docker、Podman 容器“扫盲“ 学习笔记
使用镜像启动容器,在该容器基础上修改,另存为一个新镜像

  • docker run -it docker.io/centos:latest /bin/bash
  • 配置 yum,安装软件,系统配置
  • docker commit 容器id 新镜像名称: 新镜像标签
############## 创建一个centos的容器,在kube-node1上操作 ##############
##查看所有的镜像
[root@kube-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox test 6858809bf669 5 weeks ago 1.232 MB
docker.io/busybox latest 6858809bf669 5 weeks ago 1.232 MB
docker.io/redis latest 82629e941a38 21 months ago 4.98 MB
docker.io/nginx latest 42b4762643dc 21 months ago 109.2 MB
docker.io/ubuntu latest 20bb25d32758 21 months ago 87.47 MB
docker.io/centos latest 76d6bc25b8a5 2 years ago 199.7 MB
##-it 以交互式终端的方式,根据centos镜像启动一个容器
##/bin/bash 为容器内的命令,容器内存在,才可以使用
[root@kube-node1 ~]# docker run -it docker.io/centos:latest /bin/bashh
################ 容器内安装yum, 在kube-node1上操作 ##############
#清除网络yum文件,配置本地yum
[root@d76e8f39e026 /]# rm -rf /etc/yum.repos.d/*
[root@d76e8f39e026 /]# vi /etc/yum.repos.d/centos7.repo
[centos]
name=centos7.5
baseurl=http://192.168.1.100/centos-1804
enabled=1
gpgcheck=0
##清空缓存,重新加载配置
[root@d76e8f39e026 /]# yum clean all
[root@d76e8f39e026 /]# yum repolist
........
Determining fastest mirrors
centos | 3.6 kB 00:00
(1/2): centos/group_gz | 166 kB 00:00
(2/2): centos/primary_db | 5.9 MB 00:00
repo id repo name status
centos centos7.5 9911
repolist: 9911
################ 容器内安装基础工具软件包, 在kube-node1上操作 ##############
##安装基础工具软件包
[root@d76e8f39e026 /]# yum -y install net-tools psmisc iproute vim bashcompletion tree
##清除yum缓存,减小容器大小,用于镜像制作
[root@d76e8f39e026 /]# yum clean all
##退出容器,主机名就是容器的ID号
[root@d76e8f39e026 /]# exit
################# commit自定义镜像,在kube-node1上操作 ##############
##commit 提交容器,生成新的镜像;此ID为容器的ID号
[root@kube-node1 ~]# docker commit d76e8f39e026 myos:latest
sha256:10a665c54e587d47756a00058abef86ef6b329b44937aaea34376482c9410878
##myos镜像,就是新生成的镜像
[root@kube-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myos latest 10a665c54e58 About a minute ago 317.8 MB
........
  • 使用 docker run 验证新的镜像
############## 验证新的镜像,在kube-node1上操作 ##############
##查看历史镜像,多出一个镜像层
[root@kube-node1 ~]# docker history myos:latest
IMAGE CREATED CREATED BY SIZE COMMENT
10a665c54e58 3 minutes ago /bin/bash 118.1 MB
.......
##使用新的镜像生成一个容器,容器的yum已经部署,验证成功
[root@kube-node1 ~]# docker run -it myos:latest /bin/bash
[root@5dbc2153d039 /]# yum repolist
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
repo id repo name status
centos centos7.5 9911
repolist: 9911

Dockerfile 自定义镜像

语法

  • FROM:基础镜像
  • RUN:制作镜像时执行的命令,可以有多个
  • ADD:复制文件到镜像,自动解压 (文件类型为: tar.gz 或 tar.bz2)
  • COPY:复制文件到镜像,不解压
  • MAINTAINER:镜像创建者信息
  • EXPOSE:开放的端口
  • ENV:设置变量
  • WORKDIR:定义容器默认工作目录
  • CMD: 容器启动时执行的命令,仅可以有一条CMD.
  • ENTRYPOINT:类似CMD指令的功能,用于为容器指定默认运行程序,从而使得容器像是一具单独的可执行程序

CMD不同的是,由ENTRYPOINT启动的程序不会被docker run命令行指定的参数所覆盖,而且,这些命令行参数会被当作参数传递给ENTRYPOINT指定的程序。不过,docker run 命令的--entrypoint 选项的参数可覆盖ENTRYPOINT指令指定的程序

Dockerfile 案例1

配置 yum、安装软件

FROM docker.io/centos:latest
RUN rm -f /etc/yum.repos.d/*
COPY local.repo /etc/yum.repos.d/local.repo
RUN yum install -y bash-completion net-tools iproute psmisc

创建镜像

使用 Dockerfile 工作流程,根据Dockerfile生成新的镜像,build 创建新的镜像;-t 指定新镜像的名字和标签;. 指定Dockerfile文件所在的目录

  • mkdir build
  • cd build
  • 编写 Dockerfile
########### 获取制作镜像的历史命令,在kube-node1上操作 ##############
##利用myos镜像,创建一个容器,可以查看之前制作镜像的历史命令
[root@kube-node1 ~]# docker run -it myos:latest
docker build -t imagename Dockerfile 所在目录
[root@096875f0df8d /]# history
1 rm -rf /etc/yum.repos.d/*
2 vi /etc/yum.repos.d/centos7.repo
3 yum clean all
4 yum repolist
5 yum -y install net-tools psmisc vim iproute vim bash-completiono tree
6 exit
7 history
##exit 退出,并关闭容器
[root@096875f0df8d /]# exit
########## 制作Dockerfile自动创建镜像脚本,在kube-node1上操作 ##############
##创建一个目录,名称任意定义
[root@kube-node1 ~]# mkdir aa
##进入到aa目录下
[root@kube-node1 ~]# cd aa/
##创建Dockerfile文件,文件名不能改变
[root@kube-node1 ~]# touch Dockerfile
##复制repo文件到aa目录下,用户Dockerfile中的文件复制
[root@kube-node1 aa]# cp /etc/yum.repos.d/centos7.repo .
##编写Dockerfile文件,文件名不能改变
##Dockerfile中所有的指令,必须是大写的(例如: FROM, RUN, COPY等)
#FROM 指定基础镜像,Dockerfile会对基础镜像进行编辑,生成新的镜像
#RUN 指定制作命令, 一条RUN,就代表一条要在容器内执行的命令
#COPY 复制,#即把当前目录下的文件,拷贝到容器内
[root@kube-node1 aa]# vim Dockerfile
FROM docker.io/centos:latest
RUN rm -rf /etc/yum.repos.d/*
COPY centos7.repo /etc/yum.repos.d/centos7.repo
RUN yum -y install net-tools psmisc vim iproute vim bash-completiono tree &&
yum clean all
  • docker build -t imagename Dockerfile 所在目录
########### 根据Dockerfile生成新的镜像,在kube-node1上操作 ############
##build 创建新的镜像;-t 指定新镜像的名字和标签;. 指定Dockerfile文件所在的目录
[root@kube-node1 aa]# docker build -t newos:latest .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM docker.io/centos:latest
---> 76d6bc25b8a5
Step 2 : RUN rm -rf /etc/yum.repos.d/*
---> Running in ade538eaf11c
---> a934f7feea65
Removing intermediate container ade538eaf11c
Step 3 : COPY centos7.repo /etc/yum.repos.d/centos7.repo
---> bd5e3914cda6
Removing intermediate container 80ea3d53088e
Step 4 : RUN yum -y install net-tools psmisc vim iproute vim bash-completiono
tree && yum clean all
........
##查看本地仓库镜像,newos创建成功
[root@kube-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
newos latest fb3d85796504 33 minutes ago 280.8 MB
myos latest 10a665c54e58 58 minutes ago 317.8 MB
.......

八,Dockerfile 入门

Dockerfile 创建服务镜像

Dockerfile 创建 Apache 服务案例

Dockfile中,不指定CMD时,则使用默认的启动命令;如果没有使用CMD指定启动命令,则会继承上一个镜像的默认启动命令;CMD 容器的默认启动命令,有且只能有一条

FROM myos:latest
MAINTAINER Jacob redhat@163.com
RUN yum -y install httpd
ENV LANG=C
WORKDIR /var/www/html/
EXPOSE 80 443
CMD ["httpd", "-DFOREGROUND"]
######## WORKDIR 在Dockerfile中用于定义容器默认工作目录 ###########
#使用ssh远程执行以下三条命令,f1和f2文件,最终都是创建在/root目录下
#因为每次ssh连接都是代表不同的连接,无法保持上次连接时,命令的执行状态
[root@localhost ~]# ssh host1 touch f1
[root@localhost ~]# ssh host1 cd /tmp
[root@localhost ~]# ssh host1 touch f2
##### Dockerfile和ssh类似,所以要使用 WORKDIR容器默认工作目录的指定 #####

在容器内安装并启动apache服务

###### 使用myos镜像创建一个容器,在kube-node1上操作 ############
##查看本地仓库镜像,myos镜像已经部署好了yum和基本软件包
[root@kube-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myos latest 10a665c54e58 58 minutes ago 317.8 MB
.......
####-it 以交互式终端的方式,根据centos镜像启动一个容器
##/bin/bash 为容器内的命令,容器内存在,才可以使用,不指定则会选择默认容器命令
[root@kube-node1 ~]# docker run -it myos:latest /bin/bash
[root@a670096c60ad /]#
############ 部署并启动apache服务,在kube-node1上操作 ############
####安装apache的服务软件httpd
[root@a670096c60ad /]# yum -y install httpd
#因为容器内并没有systemd的服务,无法使用systemctl来启动httpd的服务
#查看httpd的服务文件,获取环境变量文件和服务启动命令
[root@a670096c60ad /]# cat /lib/systemd/system/httpd.service
........
[Service]
........
#环境变量文件
EnvironmentFile=/etc/sysconfig/httpd
#启动命令,$OPTIONS 此环境变量为空,可以不用写
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
........
####从环境变量文件中,获取环境变量
[root@a670096c60ad /]# vim /etc/sysconfig/httpd
......
LANG=C
####设置环境变量
[root@a670096c60ad /]# LANG=C
#启动httpd服务,$OPTIONS 此环境变量为空,可以不用写
#Ctrl + C 退出
[root@54cb8bfa063d /]# /usr/sbin/httpd -DFOREGROUND
AH00558: httpd: Could not reliably determine the server's fully qualified domain
name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this
message

编写http的Dockerfile文件

########## 制作Dockerfile自动创建镜像脚本,在kube-node1上操作 ###########
##创建一个目录,名称任意定义
[root@kube-node1 ~]# mkdir bb
##进入到aa目录下
[root@kube-node1 ~]# cd bb/
##创建Dockerfile文件,文件名不能改变
[root@kube-node1 ~]# touch Dockerfile
##Dockerfile中所有的指令,必须是大写的(例如: FROM, RUN, COPY等)
#FROM 指定基础镜像,Dockerfile会对基础镜像进行编辑,生成新的镜像
#MAINTAINER 指定创建镜像者的信息
#RUN 指定制作命令, 一条RUN,就代表一条要在容器内执行的命令
#ENV 指定环境变量
#EXPOSE 开启httpd服务要使用的端口,80和443
#WORKDIR 指定启动容器后的,默认工作目录
#ADD 指拷贝,Dockerfile目录下的文件,拷贝到容器内(tar.gz,tar.bz2格式会自动解压)
#CMD 指定默认启动命令,格式示例:#ls -la 则: CMD ["ls", "-l", "-a"]
[root@kube-node1 bb]# vim Dockerfile
FROM myos:latest
MAINTAINER tarena
RUN yum -y install httpd
ENV LANG=C
EXPOSE 80 443
WORKDIR /var/www/html
ADD index.html /var/www/html/index.html
CMD ["/usr/sbin/httpd","-DFOREGROUND"]
############ 创建apache的默认访问页面,在kube-node1上操作 ##############
[root@kube-node1 bb]# echo "hello world" > index.html

运行容器

创建服务镜像:docker build -t myos:httpd

########## 使用Dockerfile文件,创建新的镜像,在kube-node1上操作 ##########
##build 创建新的镜像;-t 指定新镜像的名字和标签;. 指定Dockerfile文件所在的目录
[root@kube-node1 bb]# docker build -t myos:httpd .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM myos:latest
---> 10a665c54e58
Step 2 : RUN yum -y install httpd
---> Running in b3226773e826
.......

运行容器验证服务

############# 验证查看镜像,在kube-node1上操作 #############
##查看镜像,myos:httpd 镜像创建成功
[root@kube-node1 ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
myos httpd 019f5b48a5a0 About a minute ago 372.4 MB
......
##使用myos:httpd 镜像,创建一个容器
[root@kube-node1 ~]# docker run -itd myos:httpd
800b21aa9736bd68a521e7d5667835710b24829a136c5a0baa3e24cc319d3b70
##查看正在使用的容器
[root@kube-node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
800b21aa9736 myos:httpd "/usr/sbin/httpd -DFO" About a minute
ago Up About a minute 80/tcp, 443/tcp reverent_thompson
##查看容器的详细信息
[root@kube-node1 ~]# docker inspect 800b21aa9736
........
........
########## ENV中, PATH 指定可执行文件的搜索路径,为命令的默认查找路径 ###########
############# 如果没有指定PATH,则执行所有命令,都需要指定绝对路径 ###########
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"LANG=C"
],
############# Cmd 默认的启动命令,即:启动容器时,默认的启动命令 #############
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"/usr/sbin/httpd\" \"-DFOREGROUND\"]"
],
........
........
"Networks": {
"bridge": {
"IPAMConfig": null,
"Links": null,
"Aliases": null,
"NetworkID":
"b0cf7b16b65e272fa685ac975bce1f13647379beb8e22191d6623e30817829bc",
"EndpointID":
"f010d043874446d28892fa52903165f7370cccbc7cf449d325ad07c1c58fe6c4",
################## 容器的网关和IP地址 #########################
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:11:00:02"
........
........
####### 根据容器的IP地址,访问容器内的httpd服务,在kube-node1上操作 ########
##访问容器内的apache服务
[root@kube-node1 ~]# curl http://172.17.0.2
hello world

九、私有仓库

安装部署私有仓库

创建私有仓库

Docker、Podman 容器“扫盲“ 学习笔记

搭建私有仓库

  • 安装私有仓库(服务端yum install docker-distribution
  • 启动私有仓库,并设置开机自启动 :systemctl start docker-distribution systemctl enable docker-distribution
  • 私有仓库的配置:

    • 仓库配置文件 /etc/docker-distribution/registry/config.yml
    • 数据存储路径:/var/lib/registry
    • 默认端口号:5000

我们可以通过 curl 命令访问仓库 curl http://仓库ip:5000/v2

Docker、Podman 容器“扫盲“ 学习笔记

使用私有仓库

docker 主机修改配置文件 /etc/sysconfig/docker

  • 允许非加密方式访问仓库 INSECURE_REGISTRY='--insecure-registry 仓库IP:5000'
  • docker 仓库地址 ADD_REGISTRY='--add-registry 仓库IP:5000'

重启docker 服务 systemctl restart docker

十、外部存储卷

卷的用途

Docker 容器不保持任何数据,重要数据请使用外部卷存储(数据持久化),容器可以挂在真实机目录或共享存储为卷

  • 首先,Docker 是一个进程(随着机器的启动而运行,随着机器的停止而消失);
  • 然后,所以Docker容器内不适合存放任何的数据,容易丢失;
  • 最后,需要对Docker进行数据解耦(把Docker应用和数据存放进行分离);

主机卷的映射

真实机目录挂载到容器中提供持久化存储,目录不存在就自动创建,目录存在就直接覆盖掉,多个容器可以映射同一个目录,来达到数据共享的目的
启动容器时,使用 -v 参数映射卷 docker run -it -v 真实目录: 容器内目录 docker.io/centos: latest

多主机共享目录

有多台 docker 主机的情况下,我们也可以使用共享存储,来作为docker卷服务,可以实现多主机之间多容器的共享卷服务
Docker、Podman 容器“扫盲“ 学习笔记

十一,发布 docker 服务

怎么访问 docker 服务

默认容器可以访问宿主机,但外部网络的主机不可以访问容器内的资源,解决这个问题的最佳方法是端口绑定,容器可以与宿主机的端口进行绑定,从而把宿主机变成对应的服务宿主机容器内部服务端口绑定以后,用户在访问宿主机的服务端口时,就是在访问容器内部的服务

发布 docker 服务

我们使用 -p 参数把容器端口和宿主机端口绑定 -p 宿主机端口: 容器端口
例如:把宿主机变成 httpd

docker run -itd -p 80:80 docker.io/myos:httpd

例如:把宿主机变成 nginx

docker run -itd -p 80:80 docker.io/nginx:latest

Podman(podmanager):

是一个功能齐全的容器引擎,它是一个简单的无需守护的用来管理镜像、容器的工具。Podman提供了一个与Docker CLI兼容的操作方式,简单地说:alias docker=podman。大多数Podman命令都可以普通用户运行,而无需其他额外的权限。
图片

容器(Container):

指的是针对应用所需的运行环境资源(依赖库/目录/网络/用户……等)进行整体封装的技术。封装好的镜像相比虚拟机的粒度要更细,可移植性强。每个容器采用沙箱机制,相互隔离。

传统虚拟化与容器技术对比:
图片
Docker、Podman 容器“扫盲“ 学习笔记

仓库=》镜像=》容器 的关系:

  • 仓库:用来提供/存放镜像,有官方仓库(比如红帽的registry.redhat.io、刀客的docker.io),或自建私有仓库。
  • 镜像:针对某个虚拟机或某个应用封装的独立环境,作为容器的模板。
  • 容器:基于某个镜像启动的在内存中运行的实例。

图片

一、安装环境
# yum module install -y container-tools     //安装容器工具及其模块配置
# yum install -y podman-docker        //安装docker兼容包(可选)
二、访问仓库

1)设置默认的仓库地址(全局配置)
可以使用官方仓库(比如registry.access.redhat.com)、第三方仓库(比如docker.io),或者私有仓库(比如registry.lab.example.com)。

# vim /etc/containers/registries.conf
[registries.search]
registries = ['registry.lab.example.com']      //设置搜索镜像的默认仓库地址
.. ..
[registries.insecure]
registries = ['registry.lab.example.com']     //允许访问不安全的仓库(比如HTTPS证书无效或过期等情况)
.. ..

2)登录仓库(如果需要的话,比如push上传镜像时)

# podman  login  registry.lab.example.com
Username:  admin
Password: ***********
Login Succeeded!

3)搜索仓库中的镜像(比如nginx)

# podman  search  nginx
INDEX         NAME                                     DESCRIPTION   STARS   OFFICIAL   AUTOMATED
example.com   registry.lab.example.com/library/nginx
三、管理镜像

1)下载镜像到本地

# podman  pull  registry.lab.example.com/library/nginx
.. ..
          //容器存储默认工作目录 /var/lib/containers/

2)查看镜像

# podman  images             //列出本地镜像
REPOSITORY                       TAG      IMAGE ID       CREATED        SIZE
registry.lab.example.com/nginx   latest   4bb46517cac3   3 months ago   137 MB
# podman  image  inspect  4bb4       //查看xxxx镜像的详细配置信息
.. ..

3)导出/备份镜像

# podman  save  nginx > /root/nginx.tar

4)导入镜像

# podman  load  -i  /root/nginx.tar  nginx-new:latest

5)删除镜像

# podman  rmi  xxxx       //删除ID为xxxx的镜像
# podman  rmi  -a        //删除所有镜像
四、管理容器
1. 启动容器
  • 1)在后台启动一个容器(-d 后台运行)
# podman  run  -d  registry.lab.example.com/library/nginx
80b22e7bd4d789773223f5afc85808ea472e82ec72f162903cd658ed6d98091c
# podman  ps       //列出启用中的容器(结合-a选项可以列出所有)
.. ..
# podman  container  inspect  4bb4       //查看xxxx容器的详细信息
.. ..
  • 2)新启动一个容器并执行其中的命令“cat /etc/os-release”,然后删除此容器
# podman  run  --rm  registry.lab.example.com/library/nginx  cat  /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
.. ..
  • 3)启动一个容器,并进入容器内的/bin/bash命令行环境(-i 允许交互,-t 开启终端)
# podman  run  -it  registry.lab.example.com/library/nginx  /bin/bash
root@840b592a6d3f:/# nginx  -v       //检查nginx版本
nginx version: nginx/1.19.2
root@840b592a6d3f:/# ls  /usr/share/nginx/html/      //检查网页目录
50x.html  index.html
root@840b592a6d3f:/# exit           //退出容器
exit
#
  • 4)在后台启动一个nginx容器,添加端口映射(-p 本地端口:容器端口)
[root@red ~]# podman  run  -d  -p  8000:80  nginx
2b9ef8c0864149e2cf7860e903e36ba9deaa1717863f172b2bf2e5c5f3f6600c
[root@red ~]# podman  ps          //列出活动中的容器
CONTAINER ID  IMAGE                                          COMMAND               CREATED            STATUS                PORTS                 NAMES
2b9ef8c08641  registry.lab.example.com/library/nginx:latest  nginx -g daemon o...  2 minutes ago      Up 2 minutes ago      0.0.0.0:8000->80/tcp  ecstatic_maxwell
.. ..
[root@red ~]# curl  http://127.0.0.1:8000         //通过主机端口访问容器中的web站点
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
.. ..
  • 5)在后台启动一个nginx容器,将主机的/opt/webroot映射为此nginx容器的web目录(-v 本地目录:容器内目录)【持久存储】
# mkdir  /opt/webroot         //准备网页目录
# echo  "Podman Test" > /opt/webroot/index.html         //准备默认测试网页
# podman   run  -d  -p  8001:80  -v  /opt/webroot:/usr/share/nginx/html   nginx
ba64a15abdce1dbd4ed834ad061efde2f7ea421a862076468cbbd694c587f8ca

# curl  http://127.0.0.1:8001     //测试结果
Podman Test
2. 访问运行中的容器
  • 1)连接到ID值以ba64开头的(或者以-l表示最近一个容器)容器的命令行
[root@red ~]# podman  exec  -it ba64  bash
root@ba64a15abdce:/# service  nginx  status       
[ ok ] nginx is running.
root@ba64a15abdce:/# exit
exit
[root@red ~]#
  • 2)检查容器的IP地址
[root@red ~]# podman inspect ba64 | grep IPAddress
.. ..
            "SecondaryIPAddresses": null,
            "IPAddress": "10.88.0.6",
.. ..
  • 3)从主机向ID值为ba64的(或者以-l表示最近一个容器)容器传输文件
[root@red ~]# echo  AAAA  > /root/a.html     //建立测试网页
[root@red ~]# podman  cp  /root/a.html  ba64:/usr/share/nginx/html/a.html       //复制文件到容器
[root@red ~]# curl  http://127.0.0.1:8001/a.html        //确认结果
AAAA
  • 4)通过映射端口访问容器中的Web服务
[root@red ~]# curl  http://localhost:8001/       //浏览8001端口访问目标容器首页
Podman Test
[root@red ~]# curl  http://localhost:8001/a.html     //浏览指定页面
AAAA
3. 关闭/杀死容器
  • 1)关闭/杀死ID值为ba64的容器
[root@red ~]# podman  stop  ba64       //若要杀容器改用kill
ba64a15abdce1dbd4ed834ad061efde2f7ea421a862076468cbbd694c587f8ca
[root@red ~]# podman  ps  -a | grep  ba64     //检查容器状态
ba64a15abdce  registry.lab.example.com/library/nginx:latest  nginx -g daemon o...  47 minutes ago  Exited (0) 25 seconds ago  0.0.0.0:8001->80/tcp  dreamy_swirles
  • 2)重新启动被关闭的ID值为ba64的容器
[root@red ~]# podman  start  ba64       //启用已关闭的xx容器
ba64a15abdce1dbd4ed834ad061efde2f7ea421a862076468cbbd694c587f8ca
[root@red ~]# podman  ps  -a | grep  ba64     //检查容器状态
ba64a15abdce  registry.lab.example.com/library/nginx:latest  nginx -g daemon o...  48 minutes ago  Up 2 seconds ago        0.0.0.0:8001->80/tcp  dreamy_swirles
  • 3)强制删除ID值为ba64的容器
[root@red ~]# podman   rm   -f  ba64       //删除已关闭的xx容器(如果不加-f,则需要先stop此容器)
ba64a15abdce1dbd4ed834ad061efde2f7ea421a862076468cbbd694c587f8ca
[root@red ~]# podman  ps  -a | grep  ba64      //检查删除结果(无输出)
[root@red ~]#
五、为容器设置systemd服务
  • 1)启动一个容器,命名为myweb
[root@red ~]# podman  run  --name  myweb  -d  -p  80:80  -v  /opt/webroot:/usr/share/nginx/html   nginx
52e6996bef86c501731115216c84a2f48d1a03f8c1a2cad70d27e281bd642b18
  • 2)为名称为myweb的容器创建对应的systemd服务配置
[root@red ~]# cd  /etc/systemd/system/      //进入服务配置目录
[root@red system]# podman  generate  systemd  -n  myweb  --files
/etc/systemd/system/container-myweb.service
  • 3)更新systemd服务配置
[root@red system]# systemctl  daemon-reload

4)配置congtainer-myweb服务开机自启

[root@red system]# systemctl  enable  container-myweb
Created symlink /etc/systemd/system/multi-user.target.wants/container-myweb.service → /etc/systemd/system/container-myweb.service.

5)关闭当前运行的容器

[root@red system]# podman  stop  52e6
52e6996bef86c501731115216c84a2f48d1a03f8c1a2cad70d27e281bd642b18

6)重启主机后,检查是否可以访问此web

[root@red system]# reboot
.. ..
[root@server1 ~]# curl http://172.25.0.26/
Podman Test

六、使用无根(rootless)环境

通过rootless无根模式,非特权用户也可以很方便的运行容器(允许开启1024以上端口),以提高服务管理的安全性。
!!!! 确认非特权用户的起始可用端口(需要时可更改)

# cat  /proc/sys/net/ipv4/ip_unprivileged_port_start
1024

使用systemctl --user会话时,注意要直接以普通用户SSH或console控制台登录,不要使用su或sudo的方式执行。

  • 1)配置仓库

可参考man containers-registries.conf手册,
如果已经在/etc/containers/registries.conf 文件全局设置过,这里可以不做。

[zaniu@red ~]$ mkdir  -p  ~/.config/containers
[zaniu@red ~]$ vim ~/.config/containers/registries.conf  
unqualified-search-registries = ['registry.lab.example.com']
[[registry]] 
location = "registry.lab.example.com"
insecure = true     //允许访问不安全的仓库(全局配置中也需要添加仓库地址)
blocked = false
  • 2)下载(或导入)镜像
[zaniu@red ~]$ podman  login registry.lab.example.com      //登录仓库(如果仓库要求的话)
Username: admin
Password: 
Login Succeeded!
[zaniu@red ~]$ podman  pull  registry.lab.example.com/library/nginx   //下载镜像到本地
.. ..
          //用户容器存储默认工作目录 ~/.local/share/containers/
[zaniu@red ~]$ podman  images     //检查本地镜像
REPOSITORY                               TAG      IMAGE ID       CREATED        SIZE
registry.lab.example.com/library/nginx   latest   4bb46517cac3   3 months ago   137 MB

2)启动一个名为xxnginx的容器(如果SELinux要求启用的话,可以通过:Z传递安全标签)

[zaniu@red ~]$ mkdir  /home/zaniu/html
[zaniu@red ~]$ echo  zaniu  >  /home/zaniu//html/index.html
[zaniu@red ~]$ podman  run  --name  xxnginx  -d  -p  8080:80  -v  /home/zaniu/html:/usr/share/nginx/html:Z   nginx
8fa1bc2ccd14ddc57e187ffe8e0035b6bfb1c3189460b3470b3935365f5d9a85
[zaniu@red ~]$ curl  http://127.0.0.1:8080
zaniu
  • 3)创建container-xxnginx服务配置
[zaniu@red ~]$ mkdir  -p  ~/.config/systemd/user        //创建用户服务配置目录
[zaniu@red ~]$ cd  ~/.config/systemd/user      //进入用户服务配置目录
[zaniu@red user]$ podman  generate  systemd  --name  xxnginx  --files     //生成container-xxnginx服务配置
/home/zaniu/.config/systemd/user/container-xxnginx.service
  • 4)更新用户服务配置,设置开机自启动
[zaniu@red user]$ systemctl  --user  daemon-reload     //更新用户服务配置
[zaniu@red user]$ systemctl  --user  enable  container-xxnginx.service    //配置自启动
Created symlink /home/zaniu/.config/systemd/user/multi-user.target.wants/container-xxnginx.service → /home/zaniu/.config/systemd/user/container-xxnginx.service.

[zaniu@red user]$ loginctl  enable-linger       //允许为未登录的用户启动/保持后台服务
//如果linger方式无效,也可以通过用户计划任务实现开机自启动
[zhsan@red user]$ crontab -e
@reboot  systemctl  --user  start  container-xxnginx.service
  • 5)测试用户服务控制
[zaniu@red user]$ podman stop xxnginx       //停止原来手动运行的容器
[zaniu@red user]$ systemctl  --user  start  container-xxnginx.service      //启动容器服务
[zaniu@red user]$ systemctl  --user  status  container-xxnginx.service   //检查容器状态
[zaniu@red user]$ systemctl  --user  stop  container-xxnginx.service      //停止容器服务
6)重启主机后,确认仍然可以访问web
[root@red system]# reboot
.. ..
[root@server1 ~]# curl http://172.25.0.26:8080/
上一篇:语音芯片为何选择HW-VAD模式唤醒设备


下一篇:JBOSS绑定地址的问题