docker build alpine dns error

使用 alpine 构建 Ddockerfile ,导致 docker 打包失败,错误如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fetch https://mirrors.aliyun.com/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
fetch https://mirrors.aliyun.com/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
v3.13.4-69-g5bcff43ec5 [https://mirrors.aliyun.com/alpine/v3.13/main]
v3.13.4-66-g32aee0eba0 [https://mirrors.aliyun.com/alpine/v3.13/community]
OK: 13892 distinct packages available
fetch https://mirrors.aliyun.com/alpine/v3.13/main/x86_64/APKINDEX.tar.gz
WARNING: Ignoring https://mirrors.aliyun.com/alpine/v3.13/main: DNS lookup error
fetch https://mirrors.aliyun.com/alpine/v3.13/community/x86_64/APKINDEX.tar.gz
WARNING: Ignoring https://mirrors.aliyun.com/alpine/v3.13/community: DNS lookup error
ERROR: unable to select packages:
bash (no such package):
required by: world[bash]
curl (no such package):
required by: world[curl]
ERROR: Service 'microservice-users-rpc' failed to build : The command '/bin/sh -c apk update && apk add --no-cache curl bash' returned a non-zero code: 2
make: *** [docker-compose-up] Error 1
阅读更多

Docker & K8S 实践

使用 marp 制作的用于内部分享的 docker && k8s 的文档。


marp: true
theme: uncover
paginate: false
header: ‘NXDev

Docker & K8S 实践

纳星科技 张巍


Docker

是新技术吗?
解决了什么问题 ?


是新技术吗?

linux 的Namespaces + Cgroup
配合一种被称为 Union file system 的文件系统
最后打成一个包。


解决了什么问题?

  1. 对开发来说,统一了开发的环境。开发环境不一致的问题不再是问题。
  2. 对运维来说,上线只需要一条命令。 把所有的代码装进盒子。

Docs : https://docs.docker.com

安装

架构

Docker Run Gin


Docker 如何安装

https://docs.docker.com/get-docker/

Linux

1
2
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

先看看 怎么用的

gin-hello
mysql


Docker 架构

bg right:60% fit


镜像 (Image)
容器 (Container)
仓库 (Repository)


镜像(Image)

相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。

1
2
3
4
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 5.7 9cfcce23593a 5 weeks ago 448MB
redis 3.2-alpine 6e94a98d3442 21 months ago 22.9MB

容器(Container)

镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

1
2
3
4
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3548302772b1 redis:3.2-alpine "docker-entrypoint.s…" 3 weeks ago Up 3 weeks 0.0.0.0:6379->6379/tcp redis_redis_1
37259a661f27 xxiu/mysql "docker-entrypoint.s…" 3 weeks ago Up 3 weeks 0.0.0.0:3306->3306/tcp, 33060/tcp mysql_mysql_1

仓库(Repository)

仓库可看成一个代码控制中心,用来保存镜像。

  • 自己搭: Harbor
  • 阿里云:

核心技术

bg right:60% fit

Namespaces

Cgroup

Union file systems

Container format


Namespaces & Cgroup

linux 内核做资源隔离的两个概念。

所以 docker 和虚拟机的区别在于:

  • 虚拟机虚拟了整套的操作系统,
  • docker 只是在linux 内核上做了资源隔离。

Namespaces

资源隔离

bg right:68% fit


cgroup

Cgroup:控制程序对资源的占用。

  • 对进程组使用的资源总额进行限制;

  • 通过分配CPU时间片数量/磁盘IO/带宽大小,实际上就是相当于控制子进程运行的优先级。

  • 统计系统资源使用量,比如CPU使用时间,内存使用量等

  • 进程控制,恢复执行进程


Union file systems

img

  • boots:
    boot loader + kernel ,用户不可修改 (共享主机的内核)

  • root file system : 包括典型的 linux 目录结构:
    /dev /proc /bin /etc /lib /usr /tmp 等配置文件,二进制文件,库文件


AUFS (Union FS) : 支持将不同的目录挂载到虚拟目录下。

img


bg fit

bg fit


Docker Run Gin

1
2
3
4
5
6
7
8
9
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run(":8080")
}
1
go build . -o main

Dockerfile

1
2
3
4
5
FROM scratch
WORKDIR /root/
COPY main /root/main
EXPOSE 8080
CMD ["/root/main"]
1
2
3
docker build  -t ginhello .
docker ps |grep ginhello
docker run -it ginhello

1
2
3
语法
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

  • OPTIONS:
    开放的端口/挂载的文件/传入的变量…
  • IMAGE:
    正常的镜像名:
    registry.cn-beijing.aliyuncs.com/nxops/gin-hello:v0.0.2
  • COMMAND && ARG…

例如:

1
docker run -itd --name mysql-test -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql

运行 docker 的命令又长 参数又多,怎么办?


docker-compose

还是来用一个文件来描述刚才我们的 run 命令

1
2
3
4
5
6
7
8
9
# docker-compose.yml
version: '3'
services:
gin-hello:
image: registry.cn-beijing.aliyuncs.com/nxops/gin-hello:v0.0.2
build: .
restart: always
ports:
- 8080:8080

mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
version: '3'

services:
mysql:
image: mysql
build: .
volumes:
- ./data:/var/lib/mysql
- ./conf.d/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
environment:
- MYSQL_ROOT_PASSWORD=pprt123
- MYSQL_USER=pprt
- MYSQL_PASSWORD=pprt123
ports:
- 3306:3306
command: --lower-case-table-names=1 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always

接下来命令变得简单了
gin-hello

1
2
3
4
docker-compose build gin-hello
docker-compose push|pull gin-hello
docker-compose run gin-hello
docker-compose exec gin-hello bash

mysql

1
docker-compose run mysql 

K8S

K8s 是什么 ?

容器的调度和管理。


minikube

1
2
3
4
5
6
7
8
9
10
11
# 安装 kubectl
brew install kubectl

# 安装 minikube
# https://github.com/AliyunContainerService/minikube
# https://developer.aliyun.com/article/221687

curl -Lo minikube https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v1.12.1/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

## 选择环境
kubectl config use-context minikube

example :gin-hello


架构

bg fit right:80%


  • etcd保存了整个集群的状态;
  • apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
  • controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
  • scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
  • kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
  • Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
  • kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;

  • kube-dns负责为整个集群提供DNS服务
  • Ingress Controller为服务提供外网入口
  • Heapster提供资源监控
  • Dashboard提供GUI
  • Federation提供跨可用区的集群
  • Fluentd-elasticsearch提供集群日志采集、存储与查询

整体

bg fit right:75%


master

bg fit right:75%


Node

bg fit right:75%


kubernetes 它都管理了什么

资源


一切都是资源,根据需要去申请。
网络,存储,cpu,内存
有状态服务,无状态服务,任务,定时任务,配置
……

所有的资源都靠一行命令:

1
kubectl apply -f  <filename.yaml>

控制器

bg right:70% fit

应用控制

  • Deployment
  • DaemonSet
  • StatefulSet
  • Job/CronJob

应用配置

  • ConfigMap
  • Secret

访问方式

  • Service
  • Ingress

service

https://kubernetes.io/zh/docs/concepts/services-networking/service/#loadbalancer
service 的四种网络

  • ClusterIP 集群内部暴露ip,(默认)
  • NodeIP 通过每个 Node 上的 ip 和NodePort 暴露服务,NodePort 会路由到 ClusterIP
  • LoadBalancer 使用云提供商的均衡负载服务。 向外暴露服务
  • ExternalName 通过返回 CNAME 和它的值。

ingress

1
2
3
4
5
  internet
|
[ Ingress ]
--|-----|--
[ Services ]

ingress 被称为server 的 server。
被用来作为网络的七层代理
其实它就是做 Nginx 的事情


Ingress Controllers

在使用七层代理时,我们需要对代理做一些配置
比如 nginx 的 upstream proxy_pass

Ingress Controllers 通过 watch ingress,将它转化为数据平面的配置。

1
2
3
4
5
  internet
|
[ Ingress ] <-- [Ingress Controllers ] kubuctl
--|-----|-- | |
[ Services ] [etcd]<----------------

Ingress 选型

  1. Nginx Ingress
  2. Kong Ingress
  3. APISIX Ingress
  4. Traefik
  5. Haproxy

Kong

Kong = Openresty + config
Openresty = Nginx + lua


END

docker_sysctl

Sysctl 用于配置运行时的内核参数,正常情况下修改 /etc/sysctl.conf . 然后执行 sysctl -p 就能够设置成功。

当使用 Docker 启动服务时,使用 sysctl -p 来配置 docker 的参数时会出现问题。比如

1
2
sysctl: cannot stat /proc/sys/net/core/rmem_max: No such file or directory
sysctl: cannot stat /proc/sys/net/core/wmem_max: No such file or directory
阅读更多

Dockerfile编写实践

Docker 镜像是由 Layers 组成,Dockerfile 中每一条指令都会创建一个层,层数最多 127 层。

  1. 选择更小的基础镜像

    通常我们使用的镜像有 Ubuntu 、CentOs、 debian 、Alpine 。其中推荐使用 Alpine ,Alpine 的基础镜像只有 4.4M 左右,

    1.1 scratch 镜像

    ​ scratch 镜像是空镜像。如果要运行一个包含所有依赖的二进制文件,可以直接使用 scratch 作为基础镜像。

    1.2 busybox 镜像

    ​ scratch是个空镜像,如果希望镜像里可以包含一些常用的Linux工具,busybox镜像是个不错选择,镜像本身只有1.16M,非常便于构建小镜像。

阅读更多

docker build openwrt 遇到的小问题

在使用 docker 编译 openwrt 遇到了两个坑,问题不复杂,却折腾了一天。

环境如下

  • Dockerfile 定义编译 openwrt 的编译环境

  • docker-compose.yml 定义变化 openwrt 的运行配置,主要是将代码目录 data 使用 -v 映射到容器中

  • /data 代码存放目录

阅读更多

docker-compose 中的 external-links

在使用服务时使用同一台服务器的 mysql 的 docker 服务。想到 external-links 这个配置。

按照文档的配置添加了如下配置

1
2
external_links:
- mysql_mysql_1:mysql

但是配置无论如何都不成功。

https://docs.docker.com/compose/compose-file/#external_links

官方文档相关的描述,

If you’re using the version 2 or above file format, the externally-created containers must be connected to at least one of the same networks as the service that is linking to them.

也就是说想要使用 external_links 是需要两个服务在同一个网络段,这里只提了一句,对第一次写配置文件的开发者非常的不友好。

阅读更多

minikube

​​

Minikube

  1. 安装minikube

    1
    2
    3
    curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-darwin-amd64 && \
    chmod +x minikube && \
    sudo mv minikube /usr/local/bin/

    阿里修改版的

    1
    2
    curl -Lo minikube http://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/releases/v0.30.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

阅读更多

Jenkins-docker-ansible自动化上线

从11月开始到现在,项目开始从 php 转换到 nodejs + 后端服务,相应的部署环境转换到docker。

在使用纯php环境,上线比较简单,主要是代码拉取,拷贝和软链切换。 运行环境使用docker后相应的需要引入一个打包的过程,所以前面所依靠的上线部署系统无法满足当前的需求。

目前来说,Jenkins 作为自动化的流水线工具,几乎是不二的选择。

将 Jenkins 作为流水线工具,在打包阶段依赖 docker-compose。 上线阶段依赖 ansible 。

阅读更多

Harbor配置-DockerRegistry私有镜像仓库

Harbor简介

HarborVMware公司开源的企业级Docker Registry项目,其目标是帮助用户迅速搭建一个企业级的Docker registry`服务。

它以Docker公司开源的registry为基础,提供了管理UI,基于角色的访问控制(Role Based AccessControl),AD/LDAP集成、以及审计日志(Auditlogging) 等企业用户需求的功能,通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源 Docker Distribution

环境准备

  • Ubuntu 14.04
  • Docker and Docker Compose

Docker Compose 安装

1
2
3
4
5
6
sudo curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

sudo chmod +x /usr/local/bin/docker-compose

$ docker-compose --version
docker-compose version 1.22.0, build f46880fe
  • python

Harbor下载

下载Harbour版本的二进制文件 https://github.com/vmware/harbor/releases

1
2
wget https://storage.googleapis.com/harbor-releases/release-1.6.0/harbor-offline-installer-v1.6.0.tgz
tar -zxvf harbor-offline-installer-v1.6.0.tgz

官方的链接正常无法下载,感谢戴亚同学帮忙。

下载解压后进入解压的文件夹

Harbor配置

解压后目录下生成 harbor.conf 文件,根据需要修改配置文件。

Harbor启动

1
./install.sh
1
2
3
4
5
6
7
8
9
10
11
/home/zhangwei# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
136373bd5377 goharbor/harbor-jobservice:v1.6.0 "/harbor/start.sh" 2 days ago Up 2 days harbor-jobservice
e593d2a724de goharbor/nginx-photon:v1.6.0 "nginx -g 'daemon of…" 2 days ago Up 2 days (healthy) 0.0.0.0:443->443/tcp, 0.0.0.0:4443->4443/tcp, 0.0.0.0:1080->80/tcp nginx
f29c2341d237 goharbor/harbor-ui:v1.6.0 "/harbor/start.sh" 2 days ago Up 2 days (healthy) harbor-ui
a03a1bab796f goharbor/harbor-adminserver:v1.6.0 "/harbor/start.sh" 2 days ago Up 2 days (healthy) harbor-adminserver
c11b5b108311 goharbor/redis-photon:v1.6.0 "docker-entrypoint.s…" 2 days ago Up 2 days 6379/tcp redis
6d95f6c0aaf3 goharbor/harbor-db:v1.6.0 "/entrypoint.sh post…" 2 days ago Up 2 days (healthy) 5432/tcp harbor-db
2fa99bb3d06c goharbor/registry-photon:v2.6.2-v1.6.0 "/entrypoint.sh /etc…" 2 days ago Up 2 days (healthy) 5000/tcp registry
da21879d2dd1 goharbor/harbor-log:v1.6.0 "/bin/sh -c /usr/loc…" 2 days ago Up 2 days (healthy) 127.0.0.1:1514->10514/tcp harbor-log

根据需要修改docker-compose.yml 文件的端口

1
2
3
4
5
6
7
8
9
10
11
12
proxy:
image: goharbor/nginx-photon:v1.6.0
container_name: nginx
restart: always
volumes:
- ./common/config/nginx:/etc/nginx:z
networks:
- harbor
ports:
- 1080:80
- 443:443
- 4443:4443

Docker私有源配置

基本命令

1
2
3
sudo docker run -d -p 5000:5000 --restart=always  --name registry \
-v /home/docker/registry:/var/lib/registry registry:2 # 加入restart=always 跟随docker启动时自启动
# 本地启动后镜像服务器的地址为 localhost:5000

运行后会自动到docker hub 上拉取

1
2
3
sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry 2 2e2f252f3c88 4 weeks ago 33.3MB
阅读更多