一、Python 应用案例环境

  1. [root@k8s-node1 Flask]# pwd
  2. /opt/Dockerfile/Flask
  3. [root@k8s-node1 Flask]# ll
  4. total 12
  5. -rw-r--r-- 1 root root 352 Feb 1 10:08 app.py
  6. -rw-r--r-- 1 root root 518 Feb 1 10:20 Dockerfile
  7. -rw-r--r-- 1 root root 6 Feb 1 10:09 requirements.txt
  8. [root@k8s-node1 Flask]# cat app.py
  9. from flask import Flask
  10. import socket
  11. import os
  12.  
  13. app = Flask(__name__)
  14.  
  15. @app.route('/')
  16. def hello():
  17. html = "<h3>Hello {name}!</h3>" \
  18. "<b>Hostname:</b> {hostname}<br/>"
  19. return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
  20.  
  21. if __name__ == "__main__":
  22. app.run(host='0.0.0.0', port=80)
  23. [root@k8s-node1 Flask]# cat requirements.txt
  24. Flask
  25. [root@k8s-node1 Flask]# cat Dockerfile
  26. # 使用官方提供的 Python 开发镜像作为基础镜像
  27. FROM python:2.7-slim
  28.  
  29. # 将工作目录切换为 /app
  30. WORKDIR /app
  31.  
  32. # 将当前目录下的所有内容复制到 /app 下
  33. ADD . /app
  34.  
  35. # 使用 pip 命令安装这个应用所需要的依赖
  36. RUN pip install --trusted-host pypi.python.org -r requirements.txt
  37.  
  38. # 允许外界访问容器的 80 端口
  39. EXPOSE 80
  40.  
  41. # 设置环境变量
  42. ENV NAME World
  43.  
  44. # 设置容器进程为:python app.py,即:这个 Python 应用的启动命令
  45. CMD ["python", "app.py"]

Dockerfile的设计思想,是使用一些标准的原语(即大写高亮的词语),描述我们所要构建的Docker镜像,并且这些原语,都是按顺序处理的

需要注意的是,Dockerfile中的每个原语执行后,都会生成一个对应的镜像层

  1. [root@k8s-node1 Flask]# docker images|grep docker.io/python
  2. docker.io/python

二、启动容器以及相关操作

1、启动容器

  1. $ docker run -p 4000:80 helloworld

2、查看进程

  1. $ docker ps
  2. CONTAINER ID IMAGE COMMAND CREATED
  3. 4ddf4638572d helloworld "python app.py" 10 seconds ago

3、测试是否可用

  1. $ curl http://localhost:4000
  2. <h3>Hello World!</h3><b>Hostname:</b> 4ddf4638572d<br/>

4、上传镜像到仓库

  1. [root@k8s-node1 ~]# docker exec -it 900e7b6e1984 /bin/sh#
  2. # touch test.txt#
  3. # exit#
  4. [root@k8s-node1 ~]# docker tag helloworld 10.0.128.4:500/helloworld:v1#
  5. [root@k8s-node1 ~]# docker push 10.0.128.4:500/helloworld:v1#
  6. The push refers to a repository [10.0.128.4:500/helloworld]#
  7. Get https://10.0.128.4:500/v1/_ping: dial tcp 10.0.128.4:500: getsockopt: connection refused "/bin/sh" 2 days ago Exited (137) 2 days ago grave_mclean#

三、docker exec 是怎么做到进入容器里的呢?

1、docker exec 的实现原理

  1. [root@k8s-node1 Flask]# docker exec -it 43c49903582e /bin/sh
  2. # pwd
  3. /app
  4. # ls
  5. Dockerfile app.py requirements.txt test.txt

这里,我使用了docker exec 命令进入到了容器当中,在了解了Linux Namespace的隔离机制后,你应该会很自然地想到一个问题
docker exec 是怎么做到进入容器里的呢?

  1. [root@k8s-node1 Flask]# docker inspect --format '{{ .State.Pid }}' 43c49903582e
  2. 2400
  3. [root@k8s-node1 opt]# ls -l /proc/2400/ns
  4. total 0
  5. lrwxrwxrwx 1 root root 0 Feb 20 17:20 ipc -> ipc:[4026532495]
  6. lrwxrwxrwx 1 root root 0 Feb 20 17:19 mnt -> mnt:[4026532493]
  7. lrwxrwxrwx 1 root root 0 Feb 20 17:19 net -> net:[4026532498]
  8. lrwxrwxrwx 1 root root 0 Feb 20 17:20 pid -> pid:[4026532496]
  9. lrwxrwxrwx 1 root root 0 Feb 20 17:23 user -> user:[4026531837]
  10. lrwxrwxrwx 1 root root 0 Feb 20 17:20 uts -> uts:[4026532494]

这也就意味着:一个进程,可以选择加入到某个进程已有的 Namespace 当中,从而达到“进入”这个进程所在容器的目的,这正是 docker exec 的实现原理

2、docker exec 的实现原理刨析实验

1、依赖文件

  1. _startmainopen@@GLIBC_2.2.5perror@@GLIBC_2.2.5_Jv_RegisterClassesexecvp@@GLIBC_2.2.5exit@@GLIBC_2.2.5__TMC_END___ITM_registerTMCloneTable_init
  2. [root@k8s-node1 opt]# cat set_ns.c
  3. #define _GNU_SOURCE
  4. #include <fcntl.h>
  5. #include <sched.h>
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9.  
  10. #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE);} while (0)
  11.  
  12. int main(int argc, char *argv[]) {
  13. int fd;
  14.  
  15. fd = open(argv[1], O_RDONLY);
  16. if (setns(fd, 0) == -1) {
  17. errExit("setns");
  18. }
  19. execvp(argv[2], &argv[2]);
  20. errExit("execvp");
  21. }

2、执行

  1. [root@k8s-node1 opt]# gcc -o set_ns set_ns.c
  2. [root@k8s-node1 opt]# ./set_ns /proc/2400/ns/net /bin/bash
  3. [root@k8s-node1 opt]# ifconfig
  4. eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
  5. inet 172.16.6.2 netmask 255.255.255.0 broadcast 0.0.0.0
  6. inet6 fe80::42:acff:fe10:602 prefixlen 64 scopeid 0x20<link>
  7. ether 02:42:ac:10:06:02 txqueuelen 0 (Ethernet)
  8. RX packets 8 bytes 648 (648.0 B)
  9. RX errors 0 dropped 0 overruns 0 frame 0
  10. TX packets 8 bytes 648 (648.0 B)
  11. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
  12.  
  13. lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
  14. inet 127.0.0.1 netmask 255.0.0.0
  15. inet6 ::1 prefixlen 128 scopeid 0x10<host>
  16. loop txqueuelen 1 (Local Loopback)
  17. RX packets 0 bytes 0 (0.0 B)
  18. RX errors 0 dropped 0 overruns 0 frame 0
  19. TX packets 0 bytes 0 (0.0 B)
  20. TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

3、查看进程的进程的 Namespace

  1. [root@k8s-node1 opt]# ps aux|grep /bin/bash
  2. root 2615 0.1 0.0 116204 2876 pts/0 S 17:28 0:00 /bin/bash
  3. root 2652 0.0 0.0 112660 972 pts/0 R+ 17:28 0:00 grep --color=auto /bin/bash
  4. [root@k8s-node1 opt]# ls -l /proc/2615/ns/net
  5. lrwxrwxrwx 1 root root 0 Feb 20 17:30 /proc/2615/ns/net -> net:[4026532498]
  6. [root@k8s-node1 opt]# ls -l /proc/2400/ns/net
  7. lrwxrwxrwx 1 root root 0 Feb 20 17:19 /proc/2400/ns/net -> net:[4026532498]

转了一个大圈子,我其实是为你详细解读了这个操作背后,linux namespace更具体的工作原理

这种通过操作系统进程相关的知识,逐步刨析Docker容器的方法,是理解容器的一个关键思路,希望你一定要掌握

深入剖析Kubernetes学习笔记:深入理解镜像(08)的更多相关文章

  1. 深入剖析Kubernetes学习笔记:深入理解镜像(07)

    一.容器里的进程看到的文件系统又是什么样子呢? 1.你会看到好多宿主机的文件 [root@k8s-master ~]# vim ns.c [root@k8s-master ~]# gcc -o nl ...

  2. 深入剖析Kubernetes学习笔记:开篇词(00)

    一.关于Kubernetes初学的疑惑 就在这场因"容器"而起的技术变革中,kubernetes项目已经成为容器技术的事实标准,重新定义了基础设置领域对应用编排与管理的种种可能 1 ...

  3. 深入剖析Kubernetes学习笔记:预习篇(01-04)

    01 初出茅庐 1.PaaS 项目被大家接纳的一个主要原因? 就是它提供了一种名叫"应用托管". 2.像 Cloud Foundry 这样的 PaaS 项目,最核心的组件是? 一套 ...

  4. 深入剖析Kubernetes学习笔记:容器基础(05-06)

    05 :从进程说起 1.容器本身没有价值,有价值的是"容器编排" 2.什么是进程? 一旦"程序"被执行起来,它就从磁盘上的二进制文件,变成 1.计算机内存中的数 ...

  5. Kubernetes 学习笔记(一):基础概念

    个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...

  6. Kubernetes学习笔记(八):Deployment--声明式的升级应用

    概述 本文核心问题是:如何升级应用. 对于Pod的更新有两种策略: 一是删除全部旧Pod之后再创建新Pod.好处是,同一时间只会有一个版本的应用存在:缺点是,应用有一段时间不可用. 二是先创建新Pod ...

  7. 微信小程序开发:学习笔记[7]——理解小程序的宿主环境

    微信小程序开发:学习笔记[7]——理解小程序的宿主环境 渲染层与逻辑层 小程序的运行环境分成渲染层和逻辑层. 程序构造器

  8. Kubernetes学习笔记(四):服务

    服务介绍 服务是一种为一组相同功能的pod提供单一不变接入点的资源.当服务存在时,他的IP和端口不会改变.客户端通过IP和端口建立连接,这些连接会被路由到任何一个pod上.如此,客户端不需要知道每个单 ...

  9. Kubernetes学习笔记之认识Kubernetes组件

    前言:笔记知识点来源于Kubernetes官方文档说明,链接:https://kubernetes.io/docs/concepts/overview/components/ ,本记录仅仅是学习笔记记 ...

随机推荐

  1. MySQL之Innodb恢复的学习笔记

    MySQL · 引擎特性 · InnoDB 崩溃恢复过程 enum { SRV_FORCE_IGNORE_CORRUPT = 1, /*!< let the server run even if ...

  2. java反射(java.lang.reflect)---java.lang.reflect.Modifier中状态码

    1. 详情请看jvm(虚拟机)规范 java.lang.reflect.Modifier public static final int ABSTRACT 1024 public static fin ...

  3. 5.6Python数据处理篇之Sympy系列(六)---矩阵的操作

    目录 目录 前言 (一)矩阵的创建-Matrix() 1.说明: 2.源代码: 3.输出: (二)常用的构造矩阵 1.说明: 2.源代码: 3.输出: (三)基本操作 1.说明: 2.源代码: 3.输 ...

  4. LeetCode算法题-Design HashMap(Java实现)

    这是悦乐书的第299次更新,第318篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第167题(顺位题号是706).在不使用任何内置哈希表库的情况下设计HashMap.具体 ...

  5. Extjs 解决grid分页bug问题

    //从后端获取数据加载到grid中var mainStore = new HeJsonStore({ url:'xxx', autoLoad:true, pageSize:20 }) //此方法最好放 ...

  6. Collections方法的使用

    public static void main(String[] args) { // 0.给List排序 List<Integer> list = new ArrayList<In ...

  7. Maven的简单使用

    Maven使用 在官网下载maven: http://maven.apache.org/download.cgi 解压到D盘(位置随便) 配置环境变量 打开dos窗口,检测是否成功,出现如下画面表示配 ...

  8. 明天研究下jpa直接像django一样生成

    https://blog.csdn.net/yztezhl/article/details/79390714 自动生成 教程-- https://blog.csdn.net/mxjesse/artic ...

  9. [LeetCode] 4. 寻找两个有序数组的中位数

    题目链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/ 题目描述: 给定两个大小为 m 和 n 的有序数组 nums1 和 ...

  10. 苹果手机连接Wifi认证机制

    Wifi状态保持方法和nas设备 https://patents.google.com/patent/CN106793171A/zh 基于ios终端的离线wifi热点认证方法和认证系统 https:/ ...