docker学习(常用命令,镜像刻录,定制镜像)

docker常用命令

查看Docker版本

docker version

打印测试信息

sudo docker run hello-world

查看镜像

sudo docker images

查看容器

sudo docker ps -a

 

进入容器,执行bash命令。

docker exec -it webserver bash
root@3729b97e8226:/# echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html
root@3729b97e8226:/# exit
exit

 

 挂载主机目录

$ docker run -d -P \
    --name web \
    # -v /src/webapp:/usr/share/nginx/html \
    --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html \
    nginx:alpine

使用 --mount 参数时如果本地目录不存在,Docker 会报错。Docker 挂载主机目录的默认权限是 读写,用户也可以通过增加 readonly 指定为 只读

$ docker run -d -P \
    --name web \
    # -v /src/webapp:/usr/share/nginx/html:ro \
    --mount type=bind,source=/src/webapp,target=/usr/share/nginx/html,readonly \
    nginx:alpine 

 

挂载本地文件作为数据卷

$ docker run --rm -it \
   # -v $HOME/.bash_history:/root/.bash_history \
   --mount type=bind,source=$HOME/.bash_history,target=/root/.bash_history \
   ubuntu:18.04 \
   bash

root@2affd44b4667:/# history
1  ls
2  diskutil list

 

 

不需要sudo运行docker的办法

参考自https://www.runoob.com/note/51562

安装完 docker 后,执行docker相关命令,出现:

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/json: dial unix /var/run/docker.sock: connect: permission denied“

原因

摘自docker 手册上的一段话:

Manage Docker as a non-root user

The docker daemon binds to a Unix socket instead of a TCP port. By default that Unix socket is owned by the user root and other users can only access it using sudo. The docker daemon always runs as the root user.

If you dont want to use sudo when you use the docker command, create a Unix group called docker and add users to it. When the docker daemon starts, it makes the ownership of the Unix socket read/writable by the docker group

大概的意思就是:docker进程使用Unix Socket而不是TCP端口。而默认情况下,Unix socket属于root用户,需要root权限才能访问。

解决方法1

使用sudo获取管理员权限,运行docker命令

解决方法2

docker守护进程启动的时候,会默认赋予名字为docker的用户组读写Unix socket的权限,因此只要创建docker用户组,并将当前用户加入到docker用户组中,那么当前用户就有权限访问Unix socket了,进而也就可以执行docker相关命令

sudo groupadd docker     #添加docker用户组
sudo gpasswd -a $USER docker     #将登陆用户加入到docker用户组中
newgrp docker     #更新用户组
docker ps    #测试docker命令是否可以使用sudo正常使用

 

docker刻录镜像/打包系统示例(不建议使用,参见下一节)

参考自https://bbs.06climate.com/forum.php?mod=viewthread&tid=50384&fromuid=12776 (出处: 气象家园)

创建自己的镜像

#1 下载干净的ubuntu镜像
docker search ubuntu
docker pull ubuntu #干净的ubuntu
docker images

#2 基于镜像创建容器
docker run -i -t f49eec89601e /bin/bash #其中的-t是镜像的id
docker ps -a

# (本机与容器共享文件)的方法,加入-v参数
docker run -it -v /home/jinhuanz:/root f49eec89601e /bin/bash

#
sudo docker commit 7e2e33e3f556 jinhuan/ubuntu-meteorology:0.0.1

push镜像到docker hub个人的仓库

# should create id first

step1——找到本地镜像的ID:docker images

step2——登陆Hub:docker login --username=username --password=password --email=email

step3——tag:docker tag <imageID> <namespace>/<image name>:<version tag eg latest>

step4——push镜像:docker push <namespace>/<image name>

docker pull <namespace>/<image name>

即可使用。

 

注意! 慎用docker commit(参见https://yeasy.gitbook.io/docker_practice/image/commit)

原因如下:

第一,docker commit命令是对现有的系统目录的文件进行打包,如果是编译、安装软件包,那么所有的文件(包括代码编译产生的临时对象文件)也会一同打包进来,会导致镜像极为臃肿。

第二,docker镜像是分层存储的形式储存的,使用 docker commit 命令,会给旧的镜像添加了新的一层,而原先的旧的镜像内容依然存在、不会被删除。

除当前层外,之前的每一层都是不会发生改变的,换句话说,任何修改的结果仅仅是在当前层进行标记、添加、修改,而不会改动上一层。如果使用 docker commit 制作镜像,以及后期修改的话,每一次修改都会让镜像更加臃肿一次,所删除的上一层的东西并不会丢失,会一直如影随形的跟着这个镜像,即使根本无法访问到。这会让镜像更加臃肿。

第三,因为使用docker commit是对系统进行打包,因此也不知道这个镜像是如何创建的。

就是除了制作镜像的人知道执行过什么命令、怎么生成的镜像,别人根本无从得知。而且,即使是这个制作镜像的人,过一段时间后也无法记清具体的操作。这种黑箱镜像的维护工作是非常痛苦的。

使用 Dockerfile 定制镜像(请参考使用 Dockerfile 定制镜像 | Docker — 从入门到实践

镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。

Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

主要指令

FORM 指定基础镜像

RUN 执行命令

在撰写 Dockerfile 的时候,要经常提醒自己,这并不是在写 Shell 脚本,而是在定义每一层该如何构建。

层数尽量少,用&&将命令串联起来

示例脚本

FROM debian:stretch

RUN set -x; buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDepsc

编译安装命令放在一层,删除多余的库

Dockerfile写好后,构建镜像。进入Dockerfile所在的目录,命令格式为:docker build [选项] <上下文路径/URL/->

docker build -t nginx:v3 .

这个 .,实际上是在指定上下文的目录,docker build 命令会将该目录下的内容打包交给 Docker 引擎以帮助构建镜像。

一般来说,应该会将 Dockerfile 置于一个空目录下,或者项目根目录下。如果该目录下没有所需文件,那么应该把所需文件复制一份过来。如果目录下有些东西确实不希望构建时传给 Docker 引擎,那么可以用 .gitignore 一样的语法写一个 .dockerignore,该文件是用于剔除不需要作为上下文传递给 Docker 引擎的。

实际上,Dokerfile的文件名不要求必须为 Dockerfile,而且并不要求必须位于上下文目录中,详细信息参见https://yeasy.gitbook.io/docker_practice/image/build

posted @ 2024-07-13 00:47  chinagod  阅读(14)  评论(0编辑  收藏  举报