sonic容器构建

元宇宙开发者
• 阅读 6134

sonic中大量的组件运行在docker容器中,用于隔离彼此的运行环境,从而解决相互之间的互斥问题。下面我们分析一下sonic中各个容器的构建过程。

Dockerfile文件的生成过程

sonic中的容器Dockerfile文件是通过jinjia2模板文件生成的,使用j2命令。

sonic在编译过程中首先会构建一个叫sonic-slave的容易,该容器用来做编译容器,后续所有的编译过程都是在该容器中进行的。

编译容器生成Dockerfile

编译容器使用slave.mk作为makefile,其中有这样一段代码将Dockerfile.j2转换成Dockerfile

# Targets for building docker images
$(addprefix $(TARGET_PATH)/, $(SONIC_DOCKER_IMAGES)) : $(TARGET_PATH)/%.gz : .platform docker-start $$(addprefix $(DEBS_PATH)/,$$($$*.gz_DEPENDS)) $$(addprefix $(FILES_PATH)/,$$($$*.gz_FILES)) $$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*.gz_PYTHON_WHEELS)) $$(addsuffix -load,$$(addprefix $(TARGET_PATH)/,$$($$*.gz_LOAD_DOCKERS))) $$($$*.gz_PATH)/Dockerfile.j2
        $(HEADER)
        # Apply series of patches if exist
        if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && QUILT_PATCHES=../$(notdir $($*.gz_PATH)).patch quilt push -a; popd; fi
        mkdir -p $($*.gz_PATH)/debs $(LOG)
        mkdir -p $($*.gz_PATH)/files $(LOG)
        mkdir -p $($*.gz_PATH)/python-wheels $(LOG)
        sudo mount --bind $(DEBS_PATH) $($*.gz_PATH)/debs $(LOG)
        sudo mount --bind $(FILES_PATH) $($*.gz_PATH)/files $(LOG)
        sudo mount --bind $(PYTHON_WHEELS_PATH) $($*.gz_PATH)/python-wheels $(LOG)
        # Export variables for j2. Use path for unique variable names, e.g. docker_orchagent_debs
        $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_debs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DEPENDS),RDEPENDS))\n" | awk '!a[$$0]++'))
        $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_whls=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_PYTHON_WHEELS)))\n" | awk '!a[$$0]++'))
        $(eval export $(subst -,_,$(notdir $($*.gz_PATH)))_dbgs=$(shell printf "$(subst $(SPACE),\n,$(call expand,$($*.gz_DBG_PACKAGES)))\n" | awk '!a[$$0]++'))
        j2 $($*.gz_PATH)/Dockerfile.j2 > $($*.gz_PATH)/Dockerfile  #使用环境变量编译Dockfile.j2
        docker build --squash --no-cache \
                --build-arg http_proxy=$(HTTP_PROXY) \
                --build-arg https_proxy=$(HTTPS_PROXY) \
                --build-arg user=$(USER) \
                --build-arg uid=$(UID) \
                --build-arg guid=$(GUID) \
                --build-arg docker_container_name=$($*.gz_CONTAINER_NAME) \
                -t $* $($*.gz_PATH) $(LOG)
        docker save $* | gzip -c > $@
        # Clean up
        if [ -f $($*.gz_PATH).patch/series ]; then pushd $($*.gz_PATH) && quilt pop -a -f; popd; fi
        $(FOOTER)

根容器:docker-base

编译的过程首先构建一个docker-base容器。

docker-base.j2

# 根容器是debian:jessie
FROM debian:jessie 

#set up proxy 构建apt代理,会进行deb包缓存,加速编译速度
RUN echo 'Acquire::http { Proxy "http://172.17.0.2:3142";    };' >>/etc/apt/apt.conf.d/01proxy
RUN echo 'Acquire::HTTP::Proxy::download.docker.com "Direct";' >>/etc/apt/apt.conf.d/01proxy
RUN echo 'Acquire::HTTP::Proxy::get.docker.io "Direct";' >>/etc/apt/apt.conf.d/01proxy

# Clean documentation in FROM image
RUN find /usr/share/doc -depth \( -type f -o -type l \) ! -name copyright | xargs rm || true

# Clean doc directories that are empty or only contain empty directories
RUN while [ -n "$(find /usr/share/doc -depth -type d -empty -print -exec rmdir {} +)" ]; do :; done
RUN rm -rf               \
    /usr/share/man/*     \
    /usr/share/groff/*   \
    /usr/share/info/*    \
    /usr/share/lintian/* \
    /usr/share/linda/*   \
    /var/cache/man/*     \
    /usr/share/locale/*

# Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive

# Configure data sources for apt/dpkg
COPY ["dpkg_01_drop", "/etc/dpkg/dpkg.cfg.d/01_drop"]
COPY ["sources.list", "/etc/apt/sources.list"]
COPY ["no_install_recommend_suggest", "/etc/apt/apt.conf.d"]
RUN apt-get update

# Pre-install fundamental packages
RUN apt-get -y install \
    rsyslog            \
    vim-tiny           \
    perl               \
    python             \
    less               \
    gdb                \
    lsof               \
    strace             \
    tcpdump            \
    pstack             \
    net-tools          \
    sysstat            \
    dstat              \
    iotop              \
    htop               \
    lrzsz              \
    linux-base         \
    linux.perf         \
    linux-tools-3.16


# Pre-install troubleshooting packages
RUN apt-get -y install socat

COPY ["etc/rsyslog.conf", "/etc/rsyslog.conf"]
COPY ["etc/rsyslog.d/*", "/etc/rsyslog.d/"]
COPY ["root/.vimrc", "/root/.vimrc"]

# Install dependencies of supervisor
RUN apt-get -y install python-pkg-resources python-meld3

RUN mkdir -p /etc/supervisor
RUN mkdir -p /var/log/supervisor

COPY ["etc/supervisor/supervisord.conf", "/etc/supervisor/"]

RUN apt-get -y purge   \
    exim4              \
    exim4-base         \
    exim4-config       \
    exim4-daemon-light
#根据环境变量进行渲染,决定拷贝哪些deb到容器中
{% if docker_base_debs.strip() -%}
# Copy built Debian packages
{%- for deb in docker_base_debs.split(' ') %}
COPY debs/{{ deb }} debs/
{%- endfor %}

# Install built Debian packages and implicitly install their dependencies
{%- for deb in docker_base_debs.split(' ') %}
RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt debs/{{ deb }}
{%- endfor %}
{%- endif %}

{% if docker_base_dbgs.strip() -%}
# Install common debug-packages
{%- for dbg_pkg in docker_base_dbgs.split(' ') %}
RUN apt-get -y install {{ dbg_pkg }}
{%- endfor %}
{% else %}
RUN ln /usr/bin/vim.tiny /usr/bin/vim
{%- endif %}

# Clean up apt
# Remove /var/lib/apt/lists/*, could be obsoleted for derived images
# 删除所有下载的安装包,删除所有以前下载的安装包,卸载所有没有使用的包
RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
RUN rm -rf /var/lib/apt/lists/*

RUN rm -rf /tmp/*

渲染后会生成docker-base/Dockerfile文件,所以要修改容器构建Dockerfile时,不能直接修改,而是修改Dockerfile

docker-config-engine

在docker-base容器的基础上安装一些python工具以及安装一些编译生成的python库,该容器没有实际的内容,只是基础容器的功能增强。

docker-config-engine/Dockerfile.j2

# 在docker-base容器上构建
FROM docker-base

## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update

# Dependencies for sonic-cfggen
RUN apt-get install -y python-lxml python-yaml python-bitarray python-pip python-dev python-natsort

RUN pip install --upgrade pip

RUN pip install netaddr ipaddr jinja2 pyangbind==0.5.10


COPY \
python-wheels/swsssdk-2.0.1-py2-none-any.whl python-wheels/sonic_config_engine-1.0-py2-none-any.whl python-wheels/
RUN pip install \
python-wheels/swsssdk-2.0.1-py2-none-any.whl python-wheels/sonic_config_engine-1.0-py2-none-any.whl ## Clean up
RUN apt-get remove -y python-pip python-dev; apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
RUN rm -rf /debs /python-wheels

功能镜像

构建好了基础镜像后,后面的镜像都在docker-config-engine或者docker-base的基础上构建,这样的例如docker-orchagent-bfn,docker-fpm-frr,docker-teamd,docker-database等。

我们以docker-orchagent-bfn为例看一下功能镜像的Dockerfile文件:docker-orchagent-bfn/Dockerfile.j2

FROM docker-config-engine

ARG docker_container_name
RUN [ -f /etc/rsyslog.conf ] && sed -ri "s/%syslogtag%/$docker_container_name\/%syslogtag%/;" /etc/rsyslog.conf

## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update

RUN apt-get install -f -y ifupdown arping libdbus-1-3 libdaemon0 libjansson4

## Install redis-tools dependencies
## TODO: implicitly install dependencies
RUN apt-get -y install libjemalloc1

COPY \
{% for deb in docker_orchagent_debs.split(' ') -%}
debs/{{ deb }}{{' '}}
{%- endfor -%}
debs/

RUN dpkg -i \
{% for deb in docker_orchagent_debs.split(' ') -%}
debs/{{ deb }}{{' '}}
{%- endfor %}

## Clean up
RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y
## 镜像构建完毕后,删除/debs目录
RUN rm -rf /debs

COPY ["files/arp_update", "/usr/bin"]
COPY ["enable_counters.py", "/usr/bin"]
COPY ["start.sh", "orchagent.sh", "swssconfig.sh", "/usr/bin/"]
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"]

## Copy all Jinja2 template files into the templates folder
COPY ["*.j2", "/usr/share/sonic/templates/"]

ENTRYPOINT ["/usr/bin/supervisord"]
点赞
收藏
评论区
推荐文章
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
沸腾的木马 沸腾的木马
2年前
关于dorker安装的wordpress无法上传主题和插件的解决办法
首先,容器里居然没有php.ini这个文件。第二,容器里的配置文件无法编辑解决办法在php官网下载php.ini这个文件,修改后通过主机copy到容器里1、要查找容器的名称或ID,可以使用以下命令:dockerps这将显示正在运行的容器的列表,类似于以下示
Stella981 Stella981
3年前
Kubernetes Pod的数据卷Volume
概述由于容器本身是非持久化的,因此需要解决在容器中运行应用程序遇到的一些问题。首先,当容器崩溃时,kubelet将重新启动容器,但是写入容器的文件将会丢失,容器将会以镜像的初始状态重新开始;第二,在通过一个Pod中一起运行的容器,通常需要共享容器之间一些文件。Kubernetes通过存储卷解决上述的两个问题。在Docker有存储卷的概念卷,但D
Stella981 Stella981
3年前
Docker:dockerfile构建php项目 [八]
一、把项目封装成docker镜像的步骤把项目封装成docker镜像的步骤:1、先运行一个基础容器,手动制作docker镜像2、编写dockerfile,构建镜像3、测试运行二、dockerfile常用指令参考1、dockerfile常用指令:
Stella981 Stella981
3年前
Dockerfile中的expose到底有啥用
如题,看过Dockerfile常识的肯定都知道这个EXPOSE指令是暴露容器的端口。docker run的时候指定 P 或者p将容器的端口映射到宿主机上。这样外界访问宿主机就可以获取到容器提供的服务了。\P命令可以结合这个dockerfile文件中的EXPOSE暴露的端口。会将容器中的EXPOSE端口随机映射到宿主机的端口。实际
Wesley13 Wesley13
3年前
4、Docker 镜像构建
Docker镜像构建构建分为两种手动构建自动构建dockerfile手动构建首先启动一个Centos容器,然后在容器中安装一个nginxroot@node~dockerrunitnamenginxmancentosroot@b825
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
Dockerfile构建镜像及相关命令
Dockerfile镜像描述文件Dockerfile是一个包含用于组合镜像的命令的文本文档Docker通过读取Dockerfile中的指令按步自动生成镜像dockerbuildt机构/镜像名<:tagsDockerfile目录Dockerfile基础命令FROM基
Stella981 Stella981
3年前
Docker 容器健康检查
!DOCKERHEALTHCHECK(https://imgblog.csdnimg.cn/20210120134741738.jpg)Docker容器健康检查指的是在Dockerfile中使用HEALTHCHECK指令对容器的运行状态进行检查,并在dockerps的STATUS栏显示healthy/unhealt
Stella981 Stella981
3年前
Docker安全
我们知道dockerrun命令可以用来运行容器。那运行这个命令后,Docker做了哪些具体的工作呢?具体如下:1.dockerrun命令初始化。2.Docker运行lxcstart来执行run命令。3.lxcstart在容器中创建了一组namespace和ControlGroups。namespace是隔离的第一
Stella981 Stella981
3年前
Docker镜像优化:从1.16GB到22.4MB
Docker是一个供软件开发人员和系统管理员使用容器构建、运行和与分享应用程序的平台。容器是在独立环境中运行的进程,它运行在自己的文件系统上,该文件系统是使用docker镜像构建的。镜像中包含运行应用程序所需的一切(编译后的代码、依赖项、库等等)。镜像使用Dockerfile文件定义。术语dockerization或containeriz