详解挂载运行的docker容器中如何挂载文件系统

前言

感觉最近很多人都在问docker相关的问题,关于怎么操作一个已经启动的docker容器的文件系统,首先我发现这非常困难,因为 mnt的命名空间。

为了登录进入一个已经启动的docker容器,我们需要这么做:

  1. 使用nsenter来在临时挂载点上挂载整个docker容器的文件系统。
  2. 创建一个特定目录的绑定挂载来当作卷来使用。
  3. 卸载临时挂载。

好吧,开始实践。

启动一个名为charlie的docker实例:

$ docker run --name charlie -ti ubuntu bash

我想要将目录 /home/jpetazzo/Work/DOCKER/docker to /src 挂载到我的docker容器中。

nsenter

首先,需要nsenter,通过docker-enter帮助脚本来操作。因为想要挂载文件系统到docker容器中,处于安全原因,我们的docker容器是不允许这么做的。使用nsenter,我们就可以在docker容器中执行任意的命令,而不会受到任何安全限制的干扰,直接获取docker容器的root权限,如何获取docker容器的方法 就是这样

安装nsenter,通过docker-enter安装nsenter:

$ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter

使用我们的docker文件系统

想要挂载宿主主机中的目录 (/home/jpetazzo/Work/DOCKER/docker) 在docker中。

要找到docker文件系统的目录。

首先使用readlink查看docker 目录的挂载位置。

$ readlink --canonicalize /home/jpetazzo/Work/DOCKER/docker
/home/jpetazzo/go/src/github.com/docker/docker

设置环境变量:

$ HOSTPATH=/home/jpetazzo/Work/DOCKER/docker
$ REALPATH=$(readlink --canonicalize $HOSTPATH)

查看docker文件系统的挂载情况df:

$ df $REALPATH
Filesystem 1K-blocks Used Available Use% Mounted on
/sda2  245115308 156692700 86157700 65% /home/jpetazzo

指定指定docker 文件系统的环境变量

$ FILESYS=$(df -P $REALPATH | tail -n 1 | awk '{print $6}')

查看docker容器中的设备情况

因为现在没有绑定挂载或者使用 BTRFS,所以我们要查看/proc/mounts 来找到这个目录的设备文件 /home/jpetazzo 。

$ while read DEV MOUNT JUNK
> do [ $MOUNT = $FILESYS ] && break
> done </proc/mounts
$ echo $DEV
/dev/sda2

通过设备信息找到挂载情况。

$ while read A B C SUBROOT MOUNT JUNK
> do [ $MOUNT = $FILESYS ] && break
> done < /proc/self/mountinfo
$ echo $SUBROOT
/jpetazzo

很好,我们现在知道需要挂载 /dev/sda2,到这个目录 /jpetazzo, 从这个位置 指向我们需要的任何目录。

设定目录

$ SUBPATH=$(echo $REALPATH | sed s,^$FILESYS,,)

查看设备号。

$ stat --format "%t %T" $DEV
8 2

设置设备信息

$ DEVDEC=$(printf "%d %d" $(stat --format "0x%t 0x%T" $DEV))

将这些步骤集合

我们就是要验证docker容器中的路径和主机是不是一置

$ docker-enter charlie -- sh -c \
> "[ -b $DEV ] || mknod --mode 0600 $DEV b $DEVDEC"

创建临时挂载点挂载文件系统

$ docker-enter charlie -- mkdir /tmpmnt
$ docker-enter charlie -- mount $DEV /tmpmnt

确定文件系统存在挂载卷

$ docker-enter charlie -- mkdir -p /src
$ docker-enter charlie -- mount -o bind /tmpmnt/$SUBROOT/$SUBPATH /src

清理临时挂载

$ docker-enter charlie -- umount /tmpmnt
$ docker-enter charlie -- rmdir /tmpmnt

下面是一个简单实例脚本: 

#!/bin/sh
set -e
CONTAINER=charlie
HOSTPATH=/home/jpetazzo/Work/DOCKER/docker
CONTPATH=/src

REALPATH=$(readlink --canonicalize $HOSTPATH)
FILESYS=$(df -P $REALPATH | tail -n 1 | awk '{print $6}')

while read DEV MOUNT JUNK
do [ $MOUNT = $FILESYS ] && break
done </proc/mounts
[ $MOUNT = $FILESYS ] # Sanity check!

while read A B C SUBROOT MOUNT JUNK
do [ $MOUNT = $FILESYS ] && break
done < /proc/self/mountinfo
[ $MOUNT = $FILESYS ] # Moar sanity check!

SUBPATH=$(echo $REALPATH | sed s,^$FILESYS,,)
DEVDEC=$(printf "%d %d" $(stat --format "0x%t 0x%T" $DEV))

docker-enter $CONTAINER -- sh -c \
  "[ -b $DEV ] || mknod --mode 0600 $DEV b $DEVDEC"
docker-enter $CONTAINER -- mkdir /tmpmnt
docker-enter $CONTAINER -- mount $DEV /tmpmnt
docker-enter $CONTAINER -- mkdir -p $CONTPATH
docker-enter $CONTAINER -- mount -o bind /tmpmnt/$SUBROOT/$SUBPATH $CONTPATH
docker-enter $CONTAINER -- umount /tmpmnt
docker-enter $CONTAINER -- rmdir /tmpmnt

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • Docker 容器指定自定义网段的固定IP/静态IP地址

    Docker容器指定自定义网段的固定IP/静态IP地址 第一步:创建自定义网络 备注:这里选取了172.172.0.0网段,也可以指定其他任意空闲的网段 docker network create --subnet=172.172.0.0/16 docker-ice 注:docker-ice为自定义网桥的名字,可自己任意取名. 第二步:在你自定义的网段选取任意IP地址作为你要启动的container的静态IP地址 备注:这里在第二步中创建的网段中选取了172.172.0.10作为静态IP地址.这

  • Docker 教程之CentOS安装 Docker

    CentOS 系列安装 Docker Docker 支持 CentOS6 及以后的版本. CentOS6 对于 CentOS6,可以使用 EPEL 库安装 Docker,命令如下 $ sudo yum install http://mirrors.yun-idc.com/epel/6/i386/epel-release-6-8.noarch.rpm $ sudo yum install docker-io CentOS7 CentOS7 系统 CentOS-Extras 库中已带 Docker,

  • Docker配置PHP开发环境教程

    前言 笔者用的是mac开发,但是mac自带的php功能安装十分不方便,并且和线上的linux开发环境不一致.在没有用docker之前一直用vagrant配置的centos的php开发环境,但是自从有了docker之后,就不再用vagrant了. 配置自己的php镜像 首先在自己的任意一个目录下创建如下三个文件 run.sh #!/bin/bash /usr/sbin/php-fpm7.0 /usr/sbin/nginx tailf /etc/apt/sources.list sources.li

  • Docker教程之Ubuntu 安装 Docker详细介绍

    Ubuntu 系列安装 Docker 官方网站上有各种环境下的 安装指南. 通过系统自带包安装 Ubuntu 14.04 版本系统中已经自带了 Docker 包,可以直接安装. $ sudo apt-get update $ sudo apt-get install -y docker.io $ sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker $ sudo sed -i '$acomplete -F _docker docker' /et

  • Docker常用的清除容器镜像命令小结

    前言 Docker 是一个非常有趣的项目.它自己宣称可以减轻部署服务器的难度,当然我相信里面有炒作的成分.但是实际使用后,我觉得 Docker 的表现还是可圈可点的.这篇文章主要总结了Docker清除容器镜像常用的命令,下面来一起看看吧. 杀死所有running状态的容器 docker kill $(docker ps -q) 删除所有已经停止的容器 docker rm $(docker ps -a -q) 删除所有\'untagged/dangling\' ()状态的镜像 docker rmi

  • Docker 教程之基本概念(镜像,容器,仓库)详解

    镜像 Docker 包括三个基本概念 镜像(Image) 容器(Container) 仓库(Repository) 理解了这三个概念,就理解了 Docker 的整个生命周期. Docker 镜像 Docker 镜像就是一个只读的模板. 例如:一个镜像可以包含一个完整的 ubuntu 操作系统环境,里面仅安装了 Apache 或用户需要的其它应用程序. 镜像可以用来创建 Docker 容器. Docker 提供了一个很简单的机制来创建镜像或者更新现有的镜像,用户甚至可以直接从其他人那里下载一个已经

  • Docker 教程之获取镜像基础知识详解

    获取镜像 在之前的介绍中,我们知道镜像是 Docker 的三大组件之一. Docker 运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker 会从镜像仓库下载(默认是 Docker Hub 公共注册服务器中的仓库). 本章将介绍更多关于镜像的内容,包括: 从仓库获取镜像: 管理本地主机上的镜像: 介绍镜像实现的基本原理. 可以使用 docker pull 命令来从仓库获取所需要的镜像. 下面的例子将从 Docker Hub 仓库下载一个 Ubuntu 12.04 操作系统的镜像.

  • Docker创建镜像、怎么修改、上传镜像等详细介绍

    Docker 创建镜像.修改.上传镜像 –创建镜像有很多方法,用户可以从 Docker Hub 获取已有镜像并更新,也可以利用本地文件系统创建一个. 一.创建镜像 创建镜像有很多方法,用户可以从 Docker Hub 获取已有镜像并更新,也可以利用本地文件系统创建一个. 二.修改已有镜像 1.先使用下载的镜像启动容器. $ docker run -t -i training/sinatra /bin/bash root@0b2616b0e5a8:/# 注意:记住容器的 ID,稍后还会用到. 2.

  • 详解挂载运行的docker容器中如何挂载文件系统

    前言 感觉最近很多人都在问docker相关的问题,关于怎么操作一个已经启动的docker容器的文件系统,首先我发现这非常困难,因为 mnt的命名空间. 为了登录进入一个已经启动的docker容器,我们需要这么做: 使用nsenter来在临时挂载点上挂载整个docker容器的文件系统. 创建一个特定目录的绑定挂载来当作卷来使用. 卸载临时挂载. 好吧,开始实践. 启动一个名为charlie的docker实例: $ docker run --name charlie -ti ubuntu bash

  • 详解利用ELK搭建Docker容器化应用日志中心

    概述 应用一旦容器化以后,需要考虑的就是如何采集位于Docker容器中的应用程序的打印日志供运维分析.典型的比如SpringBoot应用的日志 收集.本文即将阐述如何利用ELK日志中心来收集容器化应用程序所产生的日志,并且可以用可视化的方式对日志进行查询与分析,其架构如下图所示: 架构图 镜像准备 镜像准备 ElasticSearch镜像 Logstash镜像 Kibana镜像 Nginx镜像(作为容器化应用来生产日志) 开启Linux系统Rsyslog服务 修改Rsyslog服务配置文件: v

  • 详解Shell脚本控制docker容器启动顺序

    1.遇到的问题 在分布式项目部署的过程中,经常要求服务器重启之后,应用(包括数据库)能够自动恢复使用.虽然使用docker update --restart=always containerid能够让容器自动随docker启动,但是并不能保证是在数据库启动之后启动,如果数据库未启动,那么将导致应用启动失败;网上还有一种解决方法是通过docker-compose容器编排来控制启动顺序,这个博主研究的比较少. 2.解决思路 使用Shell脚本来控制,思路大致如下 探测数据库端口来检验数据库是否启动成

  • 详解如何在 docker 容器中捕获信号

    我们可能都使用过 docker stop 命令来停止正在运行的容器,有时可能会使用 docker kill 命令强行关闭容器或者把某个信号传递给容器中的进程.这些操作的本质都是通过从主机向容器发送信号实现主机与容器中程序的交互.比如我们可以向容器中的应用发送一个重新加载信号,容器中的应用程序在接到信号后执行相应的处理程序完成重新加载配置文件的任务.本文将介绍在 docker 容器中捕获信号的基本知识. 信号(linux) 信号是一种进程间通信的形式.一个信号就是内核发送给进程的一个消息,告诉进程

  • 详解如何将Spring Boot应用跑在Docker容器中

    日常的Rest服务开发我都会首选SpringBoot,因为它本身的易用性以及自带的各种方便功能.生态等,今天就简单讲一下如何将Spring Boot应用跑在Docker容器中 项目搭建 首先打开Idea,选择初始化一个Spring Boot应用,然后一路回车下去,待Idea下载完依赖,开始编码 这里写一个简单的接口: @RestController @SpringBootApplication public class DemoApplication { @GetMapping("/hello&

  • 详解docker 允许主机ssh连接到docker容器中

    在docker容器中,安装好ssh: 1)替换掉容器中的安装源为163源 2)安装ssh服务 apt-get update apt-get install openssh-server 3)添加目录,修改ssh配置文件 mkdir -p /var/run/sshd vim /etc/pam.d/sshd 找到 session    required     pam_loginuid.so 这一行,将它注释掉 4)添加要链接过来的主机公钥 将公钥放到/root/.ssh/authorized_ke

  • 在Docker容器中不需要运行sshd的原因浅析

    当开始使用Docker时,人们经常问:"我该如何进入容器?",其他人会说"在你的容器里运行一个SSH服务器".但是,从这篇博文中你将会了解到你根本不需要运行SSHd守护进程来进入你的容器.当然,除非你的容器就是一个SSH服务器. 运行SSH服务器是很想当然的,因为它提供了进入容器的简便方式.在我们公司基本上每个人都最少使用过一次SSH.我们中有很大一部分人每天都会使用它,并且他们很熟悉公钥与私钥,无密码登录,密钥代理,甚至有时会使用端口转发和其他不常用的功能.正因如

  • Docker容器中运行flume及启动不输出运行日志问题

    flume配置文件如下: # Name the components on this agent app1.sources = r1 app1.sinks = k1 app1.channels = c1 # Describe/configure the source app1.sources.r1.type = avro app1.sources.r1.bind = 0.0.0.0 app1.sources.r1.port = 44444 # Describe the sink #a1.sink

  • Docker容器中挂载NFS共享目录的实现

    之前在https://www.jb51.net/article/205922.htm 介绍过使用Dockerfile构建ubuntu 16.04镜像,并在容器中编译执行Messy_Test项目.这里介绍下如何在容器中挂载NFS服务器上的共享目录. Dockerfile内容如下: FROM ubuntu:16.04 LABEL maintainer="FengBingchun fengbingchun@163.com" \ version="1.0" \ descri

  • 在 Docker 容器中运行 PHPMyAdmin的详细步骤

    目录 基本用法 预设服务器 使用 MySQL Docker 容器 使用 Docker Compose 简化部署 配置安装 概括 PHPMyAdmin是 MySQL 和 MariaDB 数据库的流行管理界面.它允许您使用 Web 浏览器与您的模式.表和数据进行交互.phpMyAdmin能够为你的MySQL提供直观.方便的Web管理界面,非常好用. 该项目有一个官方的 Docker 镜像,它简化了在容器化环境中的部署.以下是如何使用图像快速运行新的 PHPMyAdmin 实例. 基本用法 最简单的安

随机推荐