docker 基础操作

一、docker 基础操作

搜索镜像: 这种方法只能用于官方镜像库
例如搜索基于 Centos 操作系统的镜像
[root@root ~]# docker search centos

查看完整镜像的信息:
[root@root ~]# docker inspect id名称

拉取镜像
[root@root ~]# docker pull centos

查看本地镜像
[root@root ~]# docker image list

查看镜像详情
[root@root ~]# docker image inspect 镜像id

删除镜像
删除一个或多个,多个之间用空格隔开,可以使用镜像名称或id
[root@root ~]# docker rmi daocloud.io/library/mysql

强制删除:--force
如果镜像正在被使用中可以使用--force强制删除
[root@root ~]# docker rmi docker.io/ubuntu:latest --force

删除所有镜像
[root@root ~]# docker rmi $(docker images -q)

只查看所有镜像的id
[root@root ~]# docker images -q

Docker容器管理

创建新容器但不启动
[root@root ~]# docker create -it daocloud.io/library/centos:8 /bin/bash

创建并运行一个新Docker 容器
同一个镜像可以启动多个容器,每次执行run子命令都会运行一个全新的容器
[root@root ~]# docker run -it --restart=always centos /bin/bash

如果执行成功,说明CentOS 容器已经被启动,并且应该已经得到了 bash 提示符。
-i
捕获标准输入输出
-t
分配一个终端或控制台
--restart=always
容器随docker engine自启动,因为在重启docker的时候默认容器都会被关闭
也适用于create选项
--rm
默认情况下,每个容器在退出时,它的文件系统也会保存下来,这样一方面调试会方便些,因为你可以通过查看日志等方式来确定最终状态。另一方面,也可以保存容器所产生的数据。
但是当你仅仅需要短暂的运行一个容器,并且这些数据不需要保存,你可能就希望Docker能在容器结束时自动清理其所产生的数据。这个时候就需要--rm参数了。注意:--rm 和 -d不能共用

容器名称
--name= Assign a name to the container
--为容器分配一个名字,如果没有指定,docker会自动分配一个随机名称
是docker run子命令的参数
docker run -it --restart=always --name +你创建命名的名称 centos /bin/bash
如果只想断开和容器的连接而不关闭容器:
快捷键:ctrl+p+q

进入容器3种方式:
docker exec -it 容器id /bin/bash
docker attach 容器id bin/bash
查看容器:
只查看运行状态的容器:
[root@root ~]#docker ps

-a 查看所有容器
[root@root ~]#docker ps -a

只查看所有容器id:
[root@root ~]# docker ps -a -q

容器里在安装ip或ifconfig命令之前,查看网卡IP显示容器IP地址和端口号,如果输出是空的说明没有配置IP地址(不同的Docker容器可以通过此IP地址互相访问)

[root@root ~]# docker inspect --format='{{.NetworkSettings.IPAddress}}'  容器id

启动容器
[root@root ~]# docker start name

关闭容器:
[root@root ~]# docker stop name
[root@root ~]# docker kill name --强制终止容器

杀死所有running状态的容器
[root@root ~]# docker kill $(docker ps -q)

stop和kill的区别

docker stop命令给容器中的进程发送SIGTERM信号,默认行为是会导致容器退出,当然,容器内程序可以捕获该信号并自行处理,例如可以选择忽略。而docker kill则是给容器的进程发送SIGKILL信号,该信号将会使容器必然退出。

删除容器
[root@root ~]# docker rm 容器id或名称
要删除一个运行中的容器,添加 -f 参数

根据格式删除所有容器:
[root@root ~]# docker rm $(docker ps -qf status=exited)

重启容器:
[root@root ~]#docker restart name

暂停容器:
pause --暂停容器内的所有进程,
通过docker stats可以观察到此时的资源使用情况是固定不变的,通过docker logs -f也观察不到日志的进一步输出。

恢复容器:
unpause --恢复容器内暂停的进程,与pause参数相对应
[root@root ~]# docker start infallible_ramanujan
这里的名字是状态里面NAMES列列出的名字,这种方式同样会让容器运行在后台

让容器运行在后台:
如果在docker run后面追加-d=true或者-d,那么容器将会运行在后台模式。此时所有I/O数据只能通过网络资源或者共享卷组来进行交互。因为容器不再监听你执行docker run的这个终端命令行窗口。但你可以通过执行

docker attach来重新附着到该容器的回话中。
注:
容器运行在后台模式下,是不能使用--rm选项的(老版本是这样,新版本已经可以同时生效)
[root@root ~]#docker run -d IMAGE[:TAG] 命令
[root@root ~]#docker logs container_id [root@root ~]#打印该容器的输出
[root@root ~]# docker run -it -d --name mytest docker.io/centos /bin/sh -c "while true; do echo hello world; sleep 2; done"
37738fe3d6f9ef26152cb25018df9528a89e7a07355493020e72f147a291cd17

[root@root ~]# docker logs mytest
hello world
hello world

docker attach container_id #附加该容器的标准输出到当前命令行
[root@root ~]# docker attach mytest
hello world
hello world
.......
此时,ctrl+d等同于exit命令,按ctrl+p+q可以退出到宿主机,而保持container仍然在运行

rename
Rename a container

stats
Display a live stream of container(s) resource usage statistics
--动态显示容器的资源消耗情况,包括:CPU、内存、网络I/O

port
List port mappings or a specific mapping for the CONTAINER
--输出容器端口与宿主机端口的映射情况
[root@root ~]# docker port blog
80/tcp -> 0.0.0.0:80
容器blog的内部端口80映射到宿主机的80端口,这样可通过宿主机的80端口查看容器blog提供的服务

连接容器:
方法1.attach
[root@root ~]# docker attach 容器id //前提是容器创建时必须指定了交互shell

方法2.exec
通过exec命令可以创建两种任务:后台型任务和交互型任务
交互型任务:
[root@root ~]# docker exec -it 容器id /bin/bash
root@68656158eb8e:/ ls

后台型任务:
[root@root ~]# docker exec 容器id touch /testfile

监控容器的运行:
可以使用logs、top、events、wait这些子命令
logs:
使用logs命令查看守护式容器
可以通过使用docker logs命令来查看容器的运行日志,其中--tail选项可以指定查看最后几条日志,而-t选项则可以对日志条目附加时间戳。使用-f选项可以跟踪日志的输出,直到手动停止。
[root@root ~]# docker logs App_Container //不同终端操作
[root@root ~]# docker logs -f App_Container

top:
显示一个运行的容器里面的进程信息
[root@qroot ~]# docker top birdben/ubuntu:v1

events
Get real time events from the server
实时输出Docker服务器端的事件,包括容器的创建,启动,关闭等。
[root@root ~]# docker start loving_meninsky
loving_meninsky
[root@root ~]# docker events //不同终端操作
2017-07-08T16:39:23.177664994+08:00 network connect
df15746d60ffaad2d15db0854a696d6e49fdfcedc7cfd8504a8aac51a43de6d4
(container=50a0449d7729f94046baf0fe5a1ce2119742261bb3ce8c3c98f35c80458e3e7a,
name=bridge, type=bridge)
2017-07-08T16:39:23.356162529+08:00 container start
50a0449d7729f94046baf0fe5a1ce2119742261bb3ce8c3c98f35c80458e3e7a (image=ubuntu,
name=loving_meninsky)

wait(X)
Block until a container stops, then print its exit code
--捕捉容器停止时的退出码
执行此命令后,该命令会"hang"在当前终端,直到容器停止,此时,会打印出容器的退出码
[root@root ~]# docker wait 01d8aa //不同终端操作
137

diff
查看容器内发生改变的文件,以elated_lovelace容器为例
root@68656158eb8e:
touch c.txt

用diff查看:
包括文件的创建、删除和文件内容的改变都能看到
[root@root ~]# docker diff 容器名称
A /c.txt
C对应的文件内容的改变,A对应的均是文件或者目录的创建删除
[root@root ~]# docker diff 7287
A /a.txt
C /etc
C /etc/passwd
A /run
A /run/secrets
宿主机和容器之间相互Copy文件
cp的用法如下:
docker cp [OPTIONS] CONTAINER:PATH LOCALPATH
docker cp [OPTIONS] LOCALPATH CONTAINER:PATH
如:容器mysql中/usr/local/bin/存在docker-entrypoint.sh文件,可如下方式copy到宿主机
[root@root ~]# docker cp mysql:/usr/local/bin/docker-entrypoint.sh /root

修改完毕后,将该文件重新copy回容器
[root@root ~]# docker cp /root/docker-entrypoint.sh mysql:/usr/local/bin/

二、Docker容器镜像制作

1、容器文件系统打包

将容器的文件系统打包成tar文件,也就是把正在运行的容器直接导出为tar包的镜像文件
有两种方式(elated_lovelace为容器名)

第一种:[root@root ~]# docker export -o elated_lovelace.tar elated_lovelace
第二种:[root@root ~]# docker export 容器名称 > 镜像.tar

导入镜像归档文件到其他宿主机
[root@root ~]# docker import elated_lovelace.tar elated_lovelace:v1
注意:

如果导入镜像时没有起名字,随后可以单独起名字(没有名字和tag),可以手动加tag

 [root@root ~]# docker  tag  镜像ID  mycentos:7

2、通过容器创建本地镜像

方案:
​使用 docker commit 指令,把一个正在运行的容器,直接提交为一个镜像。commit 是提交的意思,类似告诉svn服务器我要生成一个新的版本。

例:在容器内部新建了一个文件

#进入容器操作:
[[email protected] ~]# docker exec -it 4ddf4638572d /bin/sh  
root@4ddf4638572d# touch test.txt
root@4ddf4638572d# exit
#将这个新建的文件提交到镜像中保存
[[email protected] ~]# docker commit 4ddf4638572d wing/helloworld:v2

(添加了作者及注释内容,生产时需要加上)
[[email protected] ~]# docker commit -m "my images version1" -a "wing" 108a85b1ed99 daocloud.io/ubuntu:v2

sha256:ffa8a185ee526a9b0d8772740231448a25855031f25c61c1b63077220469b057

  -m                   添加注释
  -a                   作者
  108a85b1ed99         容器环境id
  daocloud.io/ubuntu:v2    镜像名称:hub的名称/镜像名称:tag 
  -p,–pause=true        提交时暂停容器运行

3、通过Dockerfile创建镜像

docker build命令用于根据给定的Dockerfile和上下文以构建Docker镜像.

查找docker容器映射的端口:docker port 容器名/容器ID

save没有直接修改的情况下可以把镜像保存到本地(不需要运行成容器);export不能直接对镜像保存必须是镜像运行成容器的情况下才能保存;
   save和load搭配使用;export和import搭配使用;其中export是直接可以保存到本地,而commit不能直接保存到本地,需要通过save保存到本地。

Dockerfile默认放到/docker目录下,名字默认就叫Dockerfile

Dockerfile优化之一:尽量把RUN合并到一行。

docker build语法:

docker build [OPTIONS] 
例: docker build  -t  centos:v2 .

在Dockerfile文件中写入指令,每一条指令都会更新镜像的信息例如:

[[email protected] ~]# vim Dockerfile 
[[email protected] ~]# This is a comment 
FROM  daocloud.io/library/centos:7 
MAINTAINER wing [email protected]
RUN  命令1;命令2;命令3
RUN  命令

格式说明**

​ 每行命令都是以 INSTRUCTION statement 形式,就是命令+ 清单的模式。命令要大写,"#"是注解。

​ FROM 命令是告诉docker 我们的镜像什么。

​ MAINTAINER 是描述 镜像的创建人。

​ RUN 命令是在镜像内部执行。就是说他后面的命令应该是针对镜像可以运行的命令。

创建镜像
[root@root ~]# docker build -t centos:v2 .

     docker build  是docker创建镜像的命令 
     -t  镜像名称  
     "." 上下文目录,如果不用-f指定Dockerfile文件的位置和名称,默认会从上下文目录也就是这里指定的当前目录查找。

创建完成后,用这个镜像运行容器
[root@root ~]# docker run -it centos:v2 /bin/bash

4、Dockerfile实例01:容器化Python的Flask应用

目标:
用 Docker 部署一个用 Python 编写的 Web 应用。
应用代码部分:
​ 代码功能:如果当前环境中有"NAME"这个环境变量,就把它打印在"Hello"后,否则就打印"Hello world",最后再打印出当前环境的 hostname。
[root@root ~]# mkdir python_app
[root@root ~]# cd python_app
[root@root ~]# \vim app.py

from flask import Flask
import socket
import os
app = Flask(__name__)
@app.route('/')
def hello():
  html = "

Hello {name}!

" \ "Hostname: {hostname}
" return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname()) if __name__ == "__main__": app.run(host='0.0.0.0', port=80)

应用依赖:
定义在同目录下的 requirements.txt 文件里,内容如下:
[root@root ~]# vim requirements.txt
Flask
编写Dockerfile

[[email protected] ~]# vim Dockerfile
FROM python:2.7-slim
WORKDIR /app
ADD  .  /app
RUN pip install --trusted-host pypi.python.org -r requirements.txt
EXPOSE 80
ENV NAME World
CMD ["python", "app.py"]

Dockerfile文件说明

FROM python:2.7-slim

使用官方提供的 Python 开发镜像作为基础镜像

指定"python:2.7-slim"这个官方维护的基础镜像,从而免去安装 Python 等语言环境的操作。否则,这一段就得这么写了:

FROM ubuntu:latest

RUN apt-get update -y

RUN apt-get install -y python-pip python-dev build-essential

WORKDIR /app

将工作目录切换为 /app,意思是在这一句之后,Dockerfile 后面的操作都以这一句指定的 /app 目录作为当前目录。

ADD . /app
将当前目录下的所有内容复制到 /app 下,Dockerfile 里的原语并不都是指对容器内部的操作。比如 ADD,指的是把当前目录(即 Dockerfile 所在的目录)里的文件,复制到指定容器内的目录当中。

RUN pip install --trusted-host pypi.python.org -r requirements.txt

使用 pip 命令安装这个应用所需要的依赖

EXPOSE 80 //允许外界访问容器的 80 端口

ENV NAME World //设置环境变量

CMD ["python", "app.py"]

设置容器进程为:python app.py,即:这个 Python 应用的启动命令

这里app.py 的实际路径是 /app/app.py。CMD ["python", "app.py"] 等价于 "docker run python app.py"。

在使用 Dockerfile 时,可能还会看到一个叫作 ENTRYPOINT 的原语。它和 CMD 都是 Docker 容器进程启动所必需的参数,完整执行格式是:"ENTRYPOINT CMD"。

但是,默认,Docker 会提供一个隐含的 ENTRYPOINT,即:/bin/sh -c。所以,在不指定 ENTRYPOINT 时,比如在这个例子里,实际上运行在容器里的完整进程是:/bin/sh -c "python app.py",即 CMD 的内容就是 ENTRYPOINT 的参数。

基于以上原因,后面会统一称 Docker 容器的启动进程为 ENTRYPOINT,而不是 CMD。

/bin/bash -c 'pwd' 与pwd 结果一样 完整的终端命令

现在目录结构:

[[email protected] ~]# ls
Dockerfile  app.py  requirements.txt

构建镜像

[[email protected] ~]# docker build -t helloworld .
-t  给这个镜像加一个 Tag

Dockerfile 中的每个原语执行后,都会生成一个对应的镜像层。即使原语本身并没有明显地修改文件的操作(比如,ENV 原语),它对应的层也会存在。只不过在外界看来,这个层是空的。

查看结果:
[root@root ~]# docker image ls

REPOSITORY       TAG             IMAGE ID
helloworld       latest        653287cdf998

启动容器

[root@root ~]# docker run -p 4000:80 helloworld 
镜像名 helloworld 后面,什么都不用写,因为在 Dockerfile 中已经指定了 CMD。
否则,就得把进程的启动命令加在后面:
[root@root ~]# docker run -p 4000:80 helloworld python app.py

查看容器
[root@root ~]# docker ps

CONTAINER ID     IMAGE         COMMAND               CREATED
4ddf4638572d     helloworld    "python app.py"   10 seconds ago

进入容器

[[email protected] ~]# docker exec -it b69 /bin/bash

访问容器内应用

[[email protected] ~]# curl http://localhost:4000

结果如下:

Hello World!

Hostname: 4ddf4638572d

你可能感兴趣的:(docker 基础操作)