使用原生的 Windows Docker 容器

一谈到 Docker 容器,按照以往的惯性思维,那就是 Linux 容器(LXC),和 Windows 没多大关系,顶多也就是在 Windows 的 Linux 虚拟机中跑 Docker 容器。

不过自从 Windows Server 2016 开始,出现了 Windows 原生的 Docker 容器,它再也不只是 Linux 下的专利了。Docker 容器中可以运行 Windows 系统了, 每个 Windows 容器共享宿主机的 Windows 内核(--isolation=process,),或使用一个高度优化虚拟机中的 Windows 内核(--isolation=hyperv)。

我们说自 Windows Server 2016 开始,包括现在的 Windows Server 2019, Windows Server 2022, 还有桌面系统的 Windows 10 和  11 上 借助于 Docker Desktop 也能跑 Windows 容器。

原本在 Windows 桌面版上安装 Docker Desktop 就能用来运行 Linux 容器,由此可知在 Windows 桌面版上(如 Windows 7, 10, 11) 可运行两种类型的容器

  1. Linux 容器: 每个容器运行的是 Linux 实例,用 cgcroups 命名空间隔离资源。默认的,使用 Docker Desktop 的 LinuxEngine
  2. Windows 容器:容器中运行的是 Windows 实例,进程隔离模式是容器共享主 机的 Windows 内核,Hyper-V 隔离模式是容器使用高度优化虚拟机的内核。需启用 Windows 的 Hyper-V 特性,并切换 Docker Desktop 使用 WindowsEngine

阅读全文 >>

构建 AWS Lambda Python Docker 镜像

AWS 的 Lambda 在 2020-12-01 开始支持用 Docker 镜像存放代码,见 New for AWS Lambda - Container Image Support。AWS Lambda 最初的对发布包的限制是 50M, 解压后(因为执行前需要解压缩)不能超过 250M,对于压缩比小于 1/5 的包来说,要突破 50M 部署包的限制就要用 2018-11-29 推出的层(layer), 即把 Lambda 的依赖可以组织为层,每个 Lambda 可引用最多 5 个层,但最终 Lambda 加上层所解压后的大小仍然有 250 M 的限制。

对于使用了大量依赖的 Lambda,比如 Python 中用了 Pandas 之类的数学分析包,250M 的大小是不够的,所以才有了 Docker 镜像化的 Lambda, 镜像的大小限制一下蹦到 10G,要构建出一个 10G Lambda 用的 Linux 镜像, 那绝对是个巨兽,至少目前是超越我的想像力,除非往里面塞入大量的业务数据。关于 Lambda 有哪些限制,请参阅 Lambda quotas

介绍完 Lambda 引入 Docker 镜像的背景后,本文接下来只关注如何构建一个 Python Lambda 镜像,对于如何部署 Docker 化的 Lambda, 不在本文的范围之内。主要的参考文档为 AWS Lambda 官方的 Deploy Python Lambda functions with container images. 阅读全文 >>

理解 Docker Client/Server 架构, 找寻 Docker Desktop 替代品

本文继上篇 摆脱 Docker Desktop 即将到来的收费 进一步寻找符合自己需求的 Docker Desktop 替代品,前面试用过 hyperkit + minikube, Podman, 最终还是确定了用 docker-machine。之所以选择了它是基于下面几个需求:

  1. 连接 VPN 后 Docker 还要能继续工作 (通过 socket 文件和 localhost 与 Docker Host 通信不惧怕 VPN 连接. 因为 VPN 会接管路由表,所以用 IP 来连接 Docker Host 的话,VPN 连上后将可能无法访问 Docker Host)
  2. 能与 IDE 进行集成开发与调试  (IntelliJ IDEA 能与 Docker Desktop, Docker Machine, TCP socket 和 SSH 上的 Docker Host 集成调试,但无法与 Daemonless 的 Podman 集成)
  3. DOCKER_HOST 能是远程机器 (由于 Podman 设计为 Daemonless,也就没有 Docker Host, 无法进行远程构建)

本文力图更深入的理解 Docker 的架构来解释最后选择的来由,清楚了原理后可以自主创建一个 Docker Host,连 docker-machine 也可以不用。比如创建一个 AWS EC2 实例作为 Docker Host, 然后在本地执行 docker 命令进行镜像的构建与容器的运行,这时候镜像构建过程与容器执行的环境是在 EC2 上,再也不用先把本地的文件上传(scp 或 rsync) 到 EC2 上,然后 ssh  到 EC2 去执行 docker 命令了。

一个小插曲:本人曾经随手在  ~/Downloads 目录下建立一个只有 FROM busybox 一行的 Dockerfile 文件,然后运行 docker build ...  命令,结果每次都提示磁盘空间不足,本机磁盘还非常宽裕,Docker Machine 也分配了 20 G 内存,怎么会不够了呢?登入到 Docker Machine  后 df 确实没空间了。四处找原因,原来是 docker build ... 一执行,不管 3721 首先把当前目录下的所有文件全部拷贝到 Docker Machine 中去,~/Downloads 目录中下了几十个 G 的内容,所以把 Docker Machine 给挤暴掉。解决办法就是要把  Dockerfile 放到一个没有无用文件的独立目录中去,这也是为什么 Dockerfile 中的 COPY 命令只能从当前目录中拷贝文件的原因。 阅读全文 >>

摆脱 Docker Desktop 即将到来的收费

最近本人在 Mac OS X 下安装的 Docker Desktop 经常蹦出要升级的窗口,Skip this update PRO 不能用,Install & Restart  也总是失败,所以每次只能 SNOOZE。原来觉得事有蹊跷,后来才知道这或许与近日吵得沸沸扬扬的 Docker Desktop 收费计划有关。Docker Desktop 是专门为 Windows 和 Mac OS X 定制的,Mac OS X 和 Windows  都是开发人员用的平台。Linux 下可以不用 Docker Desktop,Linux 下 Docker 之间甚至一层窗户纸都没有,实际部署的 Docker 服务也是运行在 Linux 下的。

墙里边微信正在谋划着对聊天记录的云存储收年费,外边是 Docker 在向大公司和开发人员下手,这难道是美国加州版的共同富裕? 阅读全文 >>

如何调试 ECR Docker 镜像

常常因为在 AWS 上部署的 ECS 或 EKS 服务,甚至是使用了 ECR 镜像的 Lambda 服务这样或那样的原因无法启动,或其他莫名的异常,这时候最好能直接调试 ECR 上的 Docker 镜像,比调试用于打包 Docker 的源代码更接近真实环境。

要调试 Docker 镜像需要先从 ECR 中下载到 AWS 服务用的镜像,下面以运行 Java 的 Docker 为例,同时用 IntelliJ IDEA 关联源代码进行远程调试。

从 ECR 下载 Docker 镜像部分可参考 推送 Docker 镜像到 Amazon ECR 仓库, 那篇文章写作之时可能与现在略有不同。具体需直接进到 ECR 的页面,如 https://console.aws.amazon.com/ecr/repositories/private/<aws_account_id>/<ecr_name>?region=<region>,点击 View push commands 可看到用 AWS CLI 如何登陆 ECR,现在看到的在 macOS/Linux 下的命令是(假设 AWS AccountId 是 123456789, region 是 us-east-1)

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com

假如 ECR 仓库名是 test-java, 那么要下载 tag 1.0.1 的命令是 阅读全文 >>

Docker Swarm In Action

Before officially entering into Kubernetes, I hope to know something about the earlier Docker Swarm, although it is basically no long used currently. Swarm provides a cluster of Docker hosts. There is at least one Manager (or more) in the cluster, plus 0 or more Workers. The main idea is that a Docker service (container) is executed by the Swarm cluster manager, and it will find the corresponding host in the cluster to execute the container. Both Manager and Worker can to run Docker containers, but only Manager can execute management commands.

The following two pictures shows the difference between running Docker containers on a host and a Swarm cluster host.

Run all containers in one host   => Run container together

阅读全文 >>

Introduce Vagrant and common usages

Many of my demos about Kafka, Docker, Python, Kubernates, and etc. are made with Vagrant virtual machines. It is time to write a blog for some frequently used Vagrant commands. Vagrant is a member of the HashiCorp family. Others of HashiCorp's famous tools include  Terraform , Consul ,  Vault , Boundary , Packer , Nomad and Waypoint . 

Speaking of Vagrant, I have to mention the similar Docker, in fact, they are quite different, while they both give people the external feeling that they are command line control Linux. Vagrant is essentially a virtual machine shell, allowing us to use Vagrant commands to interact with the virtual machine more conveniently, instead of switching back and forth between the host machine and the virtual machine, it is more convenient to manage multiple virtual machines in one single terminal; while Docker is a container, The essence of a container is a process on the host machine, but it is isolated from the file system, process, network, etc. of the process with a namespace, making the container process look like a virtual OS.

Vagrant is a tool for the development environment, and Docker is a tool for the deployment environment; Vagrant operates a standard Linux or Windows operating system, and the Docker is very critical on image size. Docker image is usually a trimmed system, just has necessary command to run our service. Since Vagrant corresponds to a virtual machine, the operation status with Vagrant and the installed software will be retained after Vagrant virtual machine shutdown, while the operations status in Docker are all for the current container (copy-on-write), which does not affect the corresponding image , Unless it is committed as a new image with docker commit.

Understand that Vagrant is just the shell of a virtual machine, so it requires different virtual machine implementations, such as VirtualBox, Hyper-V, VMware, etc., and we can use Vagrant to interact with Docker as well. Vagrant can support multiple Operation Systems. 阅读全文 >>

Vagrant 简介与常用操作及配置

前方许多有关于 Kafka, Docker, Python 和 Kubernates 的文章都是在 Vagrant 虚拟机中做的 Demo,经常用到的一些 Vagrant 命令是时候有必要写篇日志记录下来。Vagrant 是 HashiCorp 家族中的一员,HashiCorp 旗下著名的工具还有  Terraform, ConsulVault, Boundary, Packer, NomadWaypoint

说起 Vagrant,不得不提起与之仿佛类似的 Docker,其实它们相差还是比较大的,只因它们给人的外在感觉都是命令行控制 Linux。Vagrant 实质是一个虚拟机的外挂,让我们更方便的用 Vagrant 命令与虚拟机交互,而不用在宿主机与虚拟机间来回切换,管理多个虚拟机就更得心应手了; 而 Docker 是一个容器,容器的本质是宿主机上的一个进程,只是用命名空间与该进程的文件系统,进程,网络等进行了隔离,使得该容器进程看似一个虚拟  OS。

Vagrant 是开发环境的部署工具, 而 Docker 是运行环境的部署工具; Vagrant 操作的是一个标准的 Linux 或  Windows 操作系统,而 Docker 的镜像考虑到发布服务的个头,通常是一个裁剪的系统,去除了服务器非必要的命令。既然 Vagrant 对应的是虚拟机,那么在 Vagrant 中的操作,安装的软件在 Vagrant 退出后都会保留下来,而 Docker 中操作的都是当前容器(copy-on-write),并不影响所对应的镜像, 除非用 docker commit 固化为新的镜像.

明白了 Vagrant 只是一个虚拟机的皮,那他在不同的硬件平台或操作系统下需要与不同的 Provider, 如 VirtualBox, Hyper-V, VMware 等配合工作,还能用 Vagrant 来操作 Docker。

有了 Vagrant, 从此不再需要下载不同操作系统的 ISO 安装镜像文件,耗时的逐步安装操作系统,也不用手工的下载别人安装好并导出的虚拟机文件,一切有点类似 Docker 一样从远程公共仓库中选择系统即可。

阅读全文 >>

Docker attach 后断开时不退出容器

docker attach 可以连接上 Docker 容器的标准输入,输出和错误输出。比如 docker attach 连接后就能显示容器中用 ENTRYPOINT/CMD 启动进程的输出内容内容。想要断开会话连接怎么做呢?ctrl - c, 控制台是不再显示了,可以容器也被终止了,显然这是一个危险的操作。

ctrl - c 不仅仅关闭了 docker attach 本身,因为它的默认参数 --sig-proxytrue,所以 SIGKILL 信号同时传递到了 ENTRYPOINT/CMD 的 PID 1 的进程,所以形成了双杀的效果。我们来试一下

如果是在生产环境下,用 docker attach 连接下控制台看下输出,然后不小心像终止 tail -f 命令一样用 ctrl - c  退出,结果服务断了。所以更为小心的操作还是用 docker logsdocker attach 的优势只是在于能查看实时的控制台输出。 阅读全文 >>

Kubernetes 学习笔记(二) - 部署和访问应用

前边折腾了各种安装 Kubernetes 集群的操作,还跑到 AWS 上撸了一把 EKS,也在 Kubernetes 上部署过服务。继续更深一步的学习如何部署应用和怎么通过 Service 去访问 Pod 中的应用,顺带看看内部的网络是怎么流转的。

测试平台还是以本地启动的三个 Vagrant 虚拟机组成的 Kubernetes 集群,安装方法见 Kubernetes 学习笔记(一) - 初上手

  1. k8s-master  (172.28.128.14)
  2. k8s-node1    (172.28.128.10)
  3. k8s-node2   (172.28.128.11)

测试应用的镜像为 yanbin/python-web, 代码见 github 上的 yabqiu/python-web-docker/app.py, 一个默认启动在  80 端口上的 Flask Web 应用,输出为当前 hostname  和一个唯一标识符。

部署应用

《每天5分玩转Kubernetes》里用的 Kubernetes 是 1.7 版本,其中还在用 kubectl run 的方式来部署应用(它会产生一个隐式的 deployment 对象),该方式已在 Kubernetes 1.12 中不推荐使用了,建议用 kubectl create deployment...,而实际中更应该用 yaml 文件编排后再 kubectl apply -f <your-yaml-file>, 这样多种对象可以编写在一起,更方便日后同样的命令更新各种对象,或者用 kubectl delete -f <your-yam-file> 批量删除所创建的对象。 阅读全文 >>