# Docker

# docker基本命令

service docker start		//开启docker服务
systemctl restart docker	//重启docker
docker search ubuntu  		//搜索镜像
docker pull                 //下载镜像
docker images     	        // 查看下载的镜像
docker ps                   //查看正在运行的容器
docker ps -a                // 查看容器列表

docker re/start unbuntu    //重启/开启容器ubuntu
docker stop ubuntu    	   //停止容器ubuntu
docker attach ubuntu 	   //连接容器ubuntu
docker rm ubuntu 		   //删除容器
docker rmi ubuntu 		   //删除镜像

docker run -it --name myubuntu -p 80:8080 -p 22:22 ubuntu /bin/bash  //创建并使用镜像

docker exec -it a62 /bin/bash   //进入container_id为a62的容器

Docker 的tag更加灵活,

Docker 将文件等信息的变动抽象为一次次的commit,每一次commit以后可能走向不同的分支,

当我们完成Docker file的构建后,会生成一串无规则的字符串代表此次生成的ID,

此时,tag的作用就是为他创建一个友好的名称,方便我们对镜像库的管理

docker tag medicean/vulapps:c_cmseasy_1 pentest:v1   //命名tag

img

docker run -d -it pentest:v1 	    //启动进程,并守护进程  -d用来开启后台守护进程
docker exec -it 88f /bin/bash		//进入镜像中的shell
service --status-all				//查看开启的服务

docker restart 容器ID    //重启

如果直接建立容器,不映射端口的话,只能通过docker的IP访问网站。

 docker run -d -it -p 8080:80 pentest:v1	//端口映射

就能直接通过虚拟机ip加端口访问

进入容器

docker attach 容器ID
docker exec -it 容器ID /bin/bash 

退出容器

exit  或
Ctrl+P+Q

# 新建一个Docker镜像

# 1.新建一个目录和一个Dockerfile

# mkdir suui
# cd suui
# touch Dockerfile

用文本编辑器打开Dockerfile文件,我喜欢用nano,因为简单操作,也可以用vim

Dockerfile中每一条指令都创建镜像的一层,例如:

# This is a comment 
FROM ubuntu:14.04 
MAINTAINER  Docker Newbee <newbee@docker.com> 
RUN apt-get -qq update 
RUN apt-get -qqy install ruby ruby-dev 
#RUN gem install suui

Dockerfile基本的语法是

使用  #来注释    
FROM 指令告诉 Docker 使用哪个镜像作为基础 
接着是维护者的信息   
RUN 开头的指令会在创建中运行,比如安装一个软件包,在这里使用apt-get来安装了一些软件

每一个指令都会在镜像上创建一个新的层,每一个指令的前缀都必须是大写的。

第一条FROM,指定使用哪个镜像源

RUN 指令告诉docker 在镜像内执行命令,安装了什么…

# 2.编写完成Dockerfile后可以使用docker build 来生成镜像

# docker build -t newuser/ubuntu:v3 . 

其中 -t 标记来添加tag,指定新的镜像的用户信息。“.”是Dockerfile所在的路径(当前目录),也可以替换为一个具体的 Dockerfile的路径。

通俗来讲: -t :指定要创建的目标镜像名 . :Dockerfile 文件所在目录,可以指定Dockerfile 的绝对路径

可以看到 build进程在执行操作。

它要做的第一件事情就是上传这个Dockerfile 内容,因为所有的操作都要 依据Dockerfile来进行。

然后Dockfile中的指令被一条一条的执行。每一步都创建了一个新的容器,在容器中执行指令并提交修改。

当所有的指令都执行完毕之后,返回了最终的镜像 id。

所有的中间步骤所产生的容器都被删除和清理了。

新的镜像创建完之后我们就可以使用`docker images来查看,然后就可以使用该镜像了

*注意一个镜像不能超过127层

Docker 允许你在容器内运行应用程序, 使用 docker run 命令来在容器内运行一个应用程序。

输出Hello world,输入命令 docker run ubuntu:14.04 /bin/echo "Hello world"

各个参数解析:
docker: Docker 的二进制执行文件。

run:与前面的 docker 组合来运行一个容器。

ubuntu:14.04指定要运行的镜像,Docker首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。

/bin/echo "Hello world": 在启动的容器里执行的命令

以上命令完整的意思可以解释为:Docker 以 ubuntu14.04镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。

# 3.运行交互式的容器

通过docker的两个参数 -i -t,让docker运行的容器实现”对话”的能力

docker run -i -t ubuntu:14.04 /bin/bash

各个参数解析:

-t:在新容器内指定一个伪终端或终端。
-i:允许你对容器内的标准输入 (STDIN) 进行交互。

可以使用ls查看当前目录下的文件,cat /proc/version查看当前系统的版本信息

运行exit命令或者使用CTRL+D来退出容器

# 4.后台模式

使用以下命令创建一个以进程方式运行的容器

docker run -d ubuntu:14.04 /bin/sh -c "while true; do echo hello world; sleep 1; done"

# 5.停止容器

使用docker stop来停止容器


如何创建一个docker镜像 (opens new window) 如何使用Dockerhub (opens new window)

# 将容器的状态保存为镜像

docker commit c43c web1  //容器ID,镜像名

更为标准的如下:

$ sudo docker commit -m "Added json gem" -a "Docker Newbee" 0b2616b0e5a8 ouruser/sinatra:v2
//其中,-m 来指定提交的说明信息,跟我们使用的版本控制工具一样;-a 可以指定更新的用户信息;
//之后是用来创建镜像的容器的 ID;最后指定目标镜像的仓库名和 tag 信息。创建成功后会返回这个镜像的 ID 信息。

将主机/www/runoob目录拷贝到容器96f7f14e99ab的/www目录下。

docker cp /www/runoob 96f7f14e99ab:/www/

将主机/www/runoob目录拷贝到容器96f7f14e99ab中,目录重命名为www。

docker cp /www/runoob 96f7f14e99ab:/www

将容器96f7f14e99ab的/www目录拷贝到主机的/tmp目录中。

docker cp  96f7f14e99ab:/www /tmp/

# 存储镜像

如果要导出镜像到本地文件,可以使用 docker save 命令。

docker save -o web.tar web1

# 通过dockerHub上传你构建的镜像 (opens new window)

# 什么是Docker

Docker是一个进程,一启动就两个进程,一个服务,一个守护进程。占用资源非常少,启动速度非常快,1s。 一台机器上vm虚拟机能开启3到10个实例。而ocker可以开启100到10000个容器。

docker会自动给docker容器配置一个虚拟ip地址

# 从应用架构角度理解Docker

刚开始,你只需要写一个Node.js程序,挂载一个静态网站;

然后,你做了一个用户账号系统,这时需要数据库了,比如说MySQL;

后来,为了提升性能,你引入了Memcached缓存;

终于有一天,你决定把前后端分离,这样可以提高开发效率;当用户越来越多,你又不得不使用Nginx做反向代理; 对了,随着功能越来越多,你的应用依赖也会越来越多…

总之,你的应用架构只会越来越复杂。不同的组件的安装,配置与运行步骤各不相同,于是你不得不写一个很长的文档给新同事,只为了让他搭建一个开发环境

使用Docker的话,你可以为不同的组件逐一编写Dockerfile,分别构建镜像,然后运行在各个容器中。

这样做,将复杂的架构统一了,所有组件的安装和运行步骤统一为几个简单的命令:

  • 构建Docker镜像: docker build
  • 上传Docker镜像: docker push
  • 下载Docker镜像: docker pull
  • 运行Docker容器: docker run

# 从应用部署角度理解Docker

通常,你会有开发测试生产服务器,对于某些应用,还会需要进行构建

不同步骤的依赖会有一些不同,并且在不同的服务器上执行。

如果手动地在不同的服务器上安装依赖,是件很麻烦的事情。

比如说,当你需要为Node.js应用添加一个新的npm模块,或者升级一下Node.js,是不是得重复操作很多次?

友情提示一下,手动敲命令是极易出错的,有些失误会导致致命的后果(参考Gitlab误删数据库与AWS的S3故障)。

如果使用Docker的话,开发构建测试生产将全部在Docker容器中执行,你需要为不同步骤编写不同的Dockerfile。

当依赖变化时,仅需要稍微修改Dockerfile即可。结合构建工具Jenkins (opens new window),就可以将整个部署流程自动化。

另一方面,Dockerfile将Docker镜像描述得非常精准,能够保证很强的一致性。

比如,操作系统的版本,Node.js的版本,NPM模块的版本等。

这就意味着,在本地开发环境运行成功的镜像,在构建测试生产环境中也没有问题。

还有,不同的Docker容器是依赖于不同的Docker镜像,这样他们互不干扰。

比如,两个Node.js应用可以分别使用不同版本的Node.js。

# 从集群管理角度理解Docker

架构规模越来越大的时候,你有必要引入集群了。

这就意味着,服务器由1台变成了多台,同一个应用需要运行多个备份来分担负载。

当然,你可以手动对集群的功能进行划分: Nginx服务器,Node.js服务器,MySQL服务器,测试服务器,生产服务器…这样做的好处是简单粗暴;也可以说财大气粗,因为资源闲置会非常严重。

还有一点,每次新增节点的时候,你就不得不花大量时间进行安装与配置,这其实是一种低效的重复劳动。

下载Docker镜像之后,Docker容器可以运行在集群的任何一个节点。

一方面,各个组件可以共享主机,且互不干扰;

另一方面,也不需要在集群的节点上安装和配置任何组件。

至于整个Docker集群的管理,业界有很多成熟的解决方案,例如Mesos (opens new window)Kubernetes (opens new window)Docker Swarm (opens new window)

这些集群系统提供了调度服务发现负载均衡等功能,让整个集群变成一个整体。

docker可以产生基础镜像,每加一层新的内容也形成新的镜像。每个镜像都可以去在加新的内容。变化无穷,复用资源。 docker

docker安装其它产品有两种方式 方式一:通过拉取事先别人做好的镜像 方式二:通过Dockerfile来构建新的镜像

参考文章:当 Node.js 遇见Docker (opens new window)

上次更新: 2021/5/28上午10:07:15