构建Melis系统开发的Docker镜像

本文介绍Docker的基本使用方法,包括构建开发环境、容器与镜像的关系、设备映射及进程管理等内容,帮助读者掌握Docker在实际场景中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们没有必要从头开始构建一个docker镜像完善开发系统,而是在一个相对完善的docker镜像的基础上加以扩展,达到我们的目的。

从doker hub获取原始镜像

执行

$ sudo apt install docker.io
$ sudo docker pull gcc

下载后查看当前系统的docker镜像列表:

进入docker:

首先我们看一下系统当前是没有活动的docker容器的: 

此时,我们创建一个,并且将主机的home目录映射为容器的/data/目录

sudo docker run -it -v ~/:/data  gcc /bin/bash

start up command also can be:

sudo docker run -it -v ~/:/data  $docker_image_id /bin/bash

a record entry installed after each running session

the CONTAINER ID and NAMES item are dynamic allocated each running session.

 below two commands are used to manange the running session.

sudo docker stop 94ad6ab47180
sudo docker start 94ad6ab47180

if you wnat to inteactive with the docker,you can add -i option after above command

sudo docker start 94ad6ab4718 -i

同一个内核:

在docker中获取到的内核信息和在HOST主机中获取到的内核信息相同,说明docker用的是主机的内核。

构建melis系统:

我们一步一步来,首先我们把系统放在HOST共享目录中,通过容器去编译, 

a deep usage about docker please refer:

基于Docker环境的YOLCAT语意分割模型实验环境搭建_papaofdoudou的博客-优快云博客_yolcat

other options on docker:

sudo docker exec 866a9a9a3221 ps -ef

above command just get the pid from the view of docker inside,but how to get the realy pid from the host? you can get use below commands:

sudo docker container top 866a9a9a3221

we can view the heriarchy of process by command;

pstree -p -H 308334 #308334 is a.out PID

sudo docker top serene_wu

see the log from the view of host

docker exec -d serene_wu sleep 2000
sudo docker logs serene_wu|more

docker related process

related is dockerd, containerd, containerd-shim

namespace of containerd-shim(305281)─┬─bash(305302)───a.out(308334)

containerd is in the same namespace with hosts init, and a.out in docker is in the same name space with the docker bash.

how to get the current namespace of process?

how to create  a namespace in helloworld?

#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
 
#define STACK_SIZE	(1024 * 1024)	
 
int idle(void *args)
{
	printf("I'm child process, and my pid is: %d\n", getpid());
	for (;;) {
		sleep(1);
	}
 
	return 0;
}
 
pid_t clone_wrapper(int (*func)(void *), int flag, void *args)
{
	char *stack, *stack_top;
	
	stack = (char *)malloc(STACK_SIZE);
	if (stack == NULL) {
		printf("alloc stack for child failed!\n");
		return -1;
	}
	stack_top = stack + STACK_SIZE;  /* Assume stack grows downward */
 
	return clone(func, stack_top, flag , args);
}
 
char *get_pid_ns(int pid)
{
	char bytes[32];
	
	sprintf(bytes, "/proc/%d/ns/pid", pid);
	return strdup(bytes);
}
 
int main(void)
{
	pid_t childs[2];
	char *ns_file;
	int fd;
 
	printf("I'm parent, and my pid is: %d\n", getpid());
 
	childs[0] = clone_wrapper(idle, CLONE_NEWPID, NULL);
	if (childs[0] == -1) {
		printf("error: create child thread failed!\n");
		return -1;
	}
	printf("first child's pid is: %d\n", childs[0]);
 
	ns_file = get_pid_ns(childs[0]);
	printf("%s line %d, nsfile %s.\n", __func__, __LINE__, ns_file);
	if (!ns_file) {
		printf("get child pid ns failed!\n");
		return -1;
	}
 
	fd = open(ns_file, O_RDONLY);
	if (fd == -1) {
		printf("open child pid ns failed!\n");
		return -1;
	}
 
	if (setns(fd, 0) == -1) {
		printf("set ns failed!\n");
		return -1;
	}
 
	printf("I'm parent, and my pid is: %d\n", getpid());
 
	childs[1] = clone_wrapper(idle, 0, NULL);
	if (childs[1] == -1) {
		printf("error: create child thread failed!\n");
		return -1;
	}
	printf("second child's pid is: %d\n", childs[1]);
 
	sleep(3);
 
	kill(childs[0], SIGTERM);
	kill(childs[1], SIGTERM);
 
	waitpid(childs[0], NULL, 0);
	waitpid(childs[1], NULL, 0);
 
	return 0;
}

设备映射

使用--device参数进行设备映射,使用-v(volume)参数进行目录映射,这样,就可以在DOCKER内部访问HOST主机上的设备了。

sudo docker run -it --device /dev/miscdriver -v /home/zlcao/misc/miscdrv:/data gcc

启动一个容器:

$ sudo docker run -it --name zilong --device /dev/hidraw0 -v /home/zlcao/riscv:/doc --net=host gcc bash

查看docker启动配置:

$ docker inspect zilong($container id)

注意启动容器时,一定要加上bash选项,否则后续docker start/docker attach将会失败。

docker镜像和docker容器的关系

  1. Docker 镜像(Docker Image): 镜像是一个只读的文件系统快照,它包含了一个完整的文件系统,其中包括应用程序、库、环境变量和配置文件等。镜像可以看作是应用程序的打包和分发方式,它定义了一个容器运行时所需的一切内容。镜像通常是静态的,不可修改的。

  2. Docker 容器(Docker Container): 容器是从镜像创建的运行实例。容器是一个独立的环境,包括应用程序和其依赖项,以及操作系统的部分,但容器不包括整个操作系统。容器是可运行的,可以启动、停止、暂停、删除和交互。容器在创建时是可变的,可以根据需要进行修改,但不会影响底层镜像。

关系:

  • 镜像是容器的基础。容器是根据镜像创建的,每个容器都基于一个特定的镜像运行。一个镜像可以用来创建多个容器实例。

  • 镜像是静态的,通常不会发生改变,而容器是动态的,可以启动、停止、修改和删除。多个容器可以同时运行相同的镜像,每个容器之间是独立的、隔离的环境。

  • 器在运行时会引用镜像,并在其基础上创建一个可读写的文件系统层,使其成为一个运行时实例。容器的状态和文件系统的更改可以在容器之间独立保存,不会影响其他容器或镜像。

总之,Docker 镜像是静态的、不可变的模板,用于创建 Docker 容器的运行时实例。容器是可运行、可修改的实体,它们基于镜像运行并且可以在其中托管应用程序和服务。这种分离和隔离的机制使得 Docker 成为一种强大的容器化技术,用于构建、部署和管理应用程序。

可以将 Docker 镜像和容器的关系比喻为“食谱”和“菜肴”的关系:

  1. Docker 镜像(食谱): Docker 镜像就像是一份食谱,其中包含了准备一道菜所需的所有信息,包括食材、调料、烹饪步骤等。这份食谱是静态的,不会改变,只是一份指南,告诉您如何准备一道特定的菜。

  2. Docker 容器(菜肴): Docker 容器就像是根据食谱准备的实际菜肴。容器是动态的,它是根据特定的食谱(镜像)创建的,可以启动、停止、修改和删除。每个容器实例都是独立的,就像每份菜肴都是在特定时刻根据食谱准备的。

类比的关键点:

  • 食谱(镜像)是不变的,不会随着菜肴(容器)的制作而改变。
  • 菜肴(容器)是可变的,可以根据需要进行调整和修改。
  • 多个菜肴可以使用相同的食谱(镜像)准备,而且每个菜肴都是独立的、隔离的。

这个比喻有助于理解 Docker 镜像和容器之间的关系,镜像是创建容器的基础,容器是实际运行和修改的实体。

在镜像的所有容器实例没有被删除干净时,是不能删除镜像的,如下图:

查看进程在宿主机或者DOCKER环境下的PID

sudo docker inspect -f '{{.State.Pid}}' zilong
sudo docker exec -it zilong ps aux
sudo docker top zilong

将容器保存为镜像:

$ sudo docker commit zilong zilong_images:v1.0
$ sudo docker save -o zilong_images.tar.bz2 zilong_images:v1.0

装载保存的镜像,之后就可以像其他镜像一样访问了:

 sudo docker load --input zilong_images.tar.bz2

查看创建信息-共享目录设置

用如下命令查看配置清单中的Mounts设置:

$ sudo docker inspect 8ecfddee660f

docker环境下查看挂载信息,是看不到HOST机端具体的源目录的,只会显示其所在的设备:

Reference

理解Docker容器的进程管理 - ilinux_one - 博客园

Docker基础_docker exec bash_米花町的小侦探的博客-优快云博客


结束!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值