docker 基礎(chǔ)操作

一、docker 基礎(chǔ)操作

搜索鏡像: 這種方法只能用于官方鏡像庫(kù)
例如搜索基于 Centos 操作系統(tǒng)的鏡像
[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

刪除鏡像
刪除一個(gè)或多個(gè),多個(gè)之間用空格隔開,可以使用鏡像名稱或id
[root@root ~]# docker rmi daocloud.io/library/mysql

強(qiáng)制刪除:--force
如果鏡像正在被使用中可以使用--force強(qiáng)制刪除
[root@root ~]# docker rmi docker.io/ubuntu:latest --force

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

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

Docker容器管理

創(chuàng)建新容器但不啟動(dòng)
[root@root ~]# docker create -it daocloud.io/library/centos:8 /bin/bash

創(chuàng)建并運(yùn)行一個(gè)新Docker 容器
同一個(gè)鏡像可以啟動(dòng)多個(gè)容器,每次執(zhí)行run子命令都會(huì)運(yùn)行一個(gè)全新的容器
[root@root ~]# docker run -it --restart=always centos /bin/bash

如果執(zhí)行成功,說(shuō)明CentOS 容器已經(jīng)被啟動(dòng),并且應(yīng)該已經(jīng)得到了 bash 提示符。
-i
捕獲標(biāo)準(zhǔn)輸入輸出
-t
分配一個(gè)終端或控制臺(tái)
--restart=always
容器隨docker engine自啟動(dòng),因?yàn)樵谥貑ocker的時(shí)候默認(rèn)容器都會(huì)被關(guān)閉
也適用于create選項(xiàng)
--rm
默認(rèn)情況下,每個(gè)容器在退出時(shí),它的文件系統(tǒng)也會(huì)保存下來(lái),這樣一方面調(diào)試會(huì)方便些,因?yàn)槟憧梢酝ㄟ^查看日志等方式來(lái)確定最終狀態(tài)。另一方面,也可以保存容器所產(chǎn)生的數(shù)據(jù)。
但是當(dāng)你僅僅需要短暫的運(yùn)行一個(gè)容器,并且這些數(shù)據(jù)不需要保存,你可能就希望Docker能在容器結(jié)束時(shí)自動(dòng)清理其所產(chǎn)生的數(shù)據(jù)。這個(gè)時(shí)候就需要--rm參數(shù)了。注意:--rm 和 -d不能共用

容器名稱
--name= Assign a name to the container
--為容器分配一個(gè)名字,如果沒有指定,docker會(huì)自動(dòng)分配一個(gè)隨機(jī)名稱
是docker run子命令的參數(shù)
docker run -it --restart=always --name +你創(chuàng)建命名的名稱 centos /bin/bash
如果只想斷開和容器的連接而不關(guān)閉容器:
快捷鍵:ctrl+p+q

進(jìn)入容器3種方式:
docker exec -it 容器id /bin/bash
docker attach 容器id bin/bash
查看容器:
只查看運(yùn)行狀態(tài)的容器:
[root@root ~]#docker ps

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

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

容器里在安裝ip或ifconfig命令之前,查看網(wǎng)卡IP顯示容器IP地址和端口號(hào),如果輸出是空的說(shuō)明沒有配置IP地址(不同的Docker容器可以通過此IP地址互相訪問)

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

啟動(dòng)容器
[root@root ~]# docker start name

關(guān)閉容器:
[root@root ~]# docker stop name
[root@root ~]# docker kill name --強(qiáng)制終止容器

殺死所有running狀態(tài)的容器
[root@root ~]# docker kill $(docker ps -q)

stop和kill的區(qū)別

docker stop命令給容器中的進(jìn)程發(fā)送SIGTERM信號(hào),默認(rèn)行為是會(huì)導(dǎo)致容器退出,當(dāng)然,容器內(nèi)程序可以捕獲該信號(hào)并自行處理,例如可以選擇忽略。而docker kill則是給容器的進(jìn)程發(fā)送SIGKILL信號(hào),該信號(hào)將會(huì)使容器必然退出。

刪除容器
[root@root ~]# docker rm 容器id或名稱
要?jiǎng)h除一個(gè)運(yùn)行中的容器,添加 -f 參數(shù)

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

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

暫停容器:
pause --暫停容器內(nèi)的所有進(jìn)程,
通過docker stats可以觀察到此時(shí)的資源使用情況是固定不變的,通過docker logs -f也觀察不到日志的進(jìn)一步輸出。

恢復(fù)容器:
unpause --恢復(fù)容器內(nèi)暫停的進(jìn)程,與pause參數(shù)相對(duì)應(yīng)
[root@root ~]# docker start infallible_ramanujan
這里的名字是狀態(tài)里面NAMES列列出的名字,這種方式同樣會(huì)讓容器運(yùn)行在后臺(tái)

讓容器運(yùn)行在后臺(tái):
如果在docker run后面追加-d=true或者-d,那么容器將會(huì)運(yùn)行在后臺(tái)模式。此時(shí)所有I/O數(shù)據(jù)只能通過網(wǎng)絡(luò)資源或者共享卷組來(lái)進(jìn)行交互。因?yàn)槿萜鞑辉俦O(jiān)聽你執(zhí)行docker run的這個(gè)終端命令行窗口。但你可以通過執(zhí)行

docker attach來(lái)重新附著到該容器的回話中。
注:
容器運(yùn)行在后臺(tái)模式下,是不能使用--rm選項(xiàng)的(老版本是這樣,新版本已經(jīng)可以同時(shí)生效)
[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 #附加該容器的標(biāo)準(zhǔn)輸出到當(dāng)前命令行
[root@root ~]# docker attach mytest
hello world
hello world
.......
此時(shí),ctrl+d等同于exit命令,按ctrl+p+q可以退出到宿主機(jī),而保持container仍然在運(yùn)行

rename
Rename a container

stats
Display a live stream of container(s) resource usage statistics
--動(dòng)態(tài)顯示容器的資源消耗情況,包括:CPU、內(nèi)存、網(wǎng)絡(luò)I/O

port
List port mappings or a specific mapping for the CONTAINER
--輸出容器端口與宿主機(jī)端口的映射情況
[root@root ~]# docker port blog
80/tcp -> 0.0.0.0:80
容器blog的內(nèi)部端口80映射到宿主機(jī)的80端口,這樣可通過宿主機(jī)的80端口查看容器blog提供的服務(wù)

連接容器:
方法1.attach
[root@root ~]# docker attach 容器id //前提是容器創(chuàng)建時(shí)必須指定了交互shell

方法2.exec
通過exec命令可以創(chuàng)建兩種任務(wù):后臺(tái)型任務(wù)和交互型任務(wù)
交互型任務(wù):
[root@root ~]# docker exec -it 容器id /bin/bash
root@68656158eb8e:/ ls

后臺(tái)型任務(wù):
[root@root ~]# docker exec 容器id touch /testfile

監(jiān)控容器的運(yùn)行:
可以使用logs、top、events、wait這些子命令
logs:
使用logs命令查看守護(hù)式容器
可以通過使用docker logs命令來(lái)查看容器的運(yùn)行日志,其中--tail選項(xiàng)可以指定查看最后幾條日志,而-t選項(xiàng)則可以對(duì)日志條目附加時(shí)間戳。使用-f選項(xiàng)可以跟蹤日志的輸出,直到手動(dòng)停止。
[root@root ~]# docker logs App_Container //不同終端操作
[root@root ~]# docker logs -f App_Container

top:
顯示一個(gè)運(yùn)行的容器里面的進(jìn)程信息
[root@qroot ~]# docker top birdben/ubuntu:v1

events
Get real time events from the server
實(shí)時(shí)輸出Docker服務(wù)器端的事件,包括容器的創(chuàng)建,啟動(dòng),關(guān)閉等。
[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
--捕捉容器停止時(shí)的退出碼
執(zhí)行此命令后,該命令會(huì)"hang"在當(dāng)前終端,直到容器停止,此時(shí),會(huì)打印出容器的退出碼
[root@root ~]# docker wait 01d8aa //不同終端操作
137

diff
查看容器內(nèi)發(fā)生改變的文件,以elated_lovelace容器為例
root@68656158eb8e:
touch c.txt

用diff查看:
包括文件的創(chuàng)建、刪除和文件內(nèi)容的改變都能看到
[root@root ~]# docker diff 容器名稱
A /c.txt
C對(duì)應(yīng)的文件內(nèi)容的改變,A對(duì)應(yīng)的均是文件或者目錄的創(chuàng)建刪除
[root@root ~]# docker diff 7287
A /a.txt
C /etc
C /etc/passwd
A /run
A /run/secrets
宿主機(jī)和容器之間相互Copy文件
cp的用法如下:
docker cp [OPTIONS] CONTAINER:PATH LOCALPATH
docker cp [OPTIONS] LOCALPATH CONTAINER:PATH
如:容器mysql中/usr/local/bin/存在docker-entrypoint.sh文件,可如下方式copy到宿主機(jī)
[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、容器文件系統(tǒng)打包

將容器的文件系統(tǒng)打包成tar文件,也就是把正在運(yùn)行的容器直接導(dǎo)出為tar包的鏡像文件
有兩種方式(elated_lovelace為容器名)

第一種:[root@root ~]# docker export -o elated_lovelace.tar elated_lovelace
第二種:[root@root ~]# docker export 容器名稱 > 鏡像.tar

導(dǎo)入鏡像歸檔文件到其他宿主機(jī)
[root@root ~]# docker import elated_lovelace.tar elated_lovelace:v1
注意:

如果導(dǎo)入鏡像時(shí)沒有起名字,隨后可以單獨(dú)起名字(沒有名字和tag),可以手動(dòng)加tag

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

2、通過容器創(chuàng)建本地鏡像

方案:
?使用 docker commit 指令,把一個(gè)正在運(yùn)行的容器,直接提交為一個(gè)鏡像。commit 是提交的意思,類似告訴svn服務(wù)器我要生成一個(gè)新的版本。

例:在容器內(nèi)部新建了一個(gè)文件

#進(jìn)入容器操作:
[root@qfedu.com ~]# docker exec -it 4ddf4638572d /bin/sh  
root@4ddf4638572d# touch test.txt
root@4ddf4638572d# exit
#將這個(gè)新建的文件提交到鏡像中保存
[root@qfedu.com ~]# docker commit 4ddf4638572d wing/helloworld:v2

(添加了作者及注釋內(nèi)容,生產(chǎn)時(shí)需要加上)
[root@qfedu.com ~]# docker commit -m "my images version1" -a "wing" 108a85b1ed99 daocloud.io/ubuntu:v2

sha256:ffa8a185ee526a9b0d8772740231448a25855031f25c61c1b63077220469b057

  -m                   添加注釋
  -a                   作者
  108a85b1ed99         容器環(huán)境id
  daocloud.io/ubuntu:v2    鏡像名稱:hub的名稱/鏡像名稱:tag 
  -p,–pause=true        提交時(shí)暫停容器運(yùn)行

3、通過Dockerfile創(chuàng)建鏡像

docker build命令用于根據(jù)給定的Dockerfile和上下文以構(gòu)建Docker鏡像.

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

save沒有直接修改的情況下可以把鏡像保存到本地(不需要運(yùn)行成容器);export不能直接對(duì)鏡像保存必須是鏡像運(yùn)行成容器的情況下才能保存;
   save和load搭配使用;export和import搭配使用;其中export是直接可以保存到本地,而commit不能直接保存到本地,需要通過save保存到本地。

Dockerfile默認(rèn)放到/docker目錄下,名字默認(rèn)就叫Dockerfile

Dockerfile優(yōu)化之一:盡量把RUN合并到一行。

docker build語(yǔ)法:

docker build [OPTIONS] <PATH | URL | ->
例: docker build  -t  centos:v2 .

在Dockerfile文件中寫入指令,每一條指令都會(huì)更新鏡像的信息例如:

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

格式說(shuō)明**

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

? FROM 命令是告訴docker 我們的鏡像什么。

? MAINTAINER 是描述 鏡像的創(chuàng)建人。

? RUN 命令是在鏡像內(nèi)部執(zhí)行。就是說(shuō)他后面的命令應(yīng)該是針對(duì)鏡像可以運(yùn)行的命令。

創(chuàng)建鏡像
[root@root ~]# docker build -t centos:v2 .

     docker build  是docker創(chuàng)建鏡像的命令 
     -t  鏡像名稱  
     "." 上下文目錄,如果不用-f指定Dockerfile文件的位置和名稱,默認(rèn)會(huì)從上下文目錄也就是這里指定的當(dāng)前目錄查找。

創(chuàng)建完成后,用這個(gè)鏡像運(yùn)行容器
[root@root ~]# docker run -it centos:v2 /bin/bash

4、Dockerfile實(shí)例01:容器化Python的Flask應(yīng)用

目標(biāo):
用 Docker 部署一個(gè)用 Python 編寫的 Web 應(yīng)用。
應(yīng)用代碼部分:
? 代碼功能:如果當(dāng)前環(huán)境中有"NAME"這個(gè)環(huán)境變量,就把它打印在"Hello"后,否則就打印"Hello world",最后再打印出當(dāng)前環(huán)境的 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 = "<h3>Hello {name}!</h3>" \
      "<b>Hostname:</b> {hostname}<br/>"      
  return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
if __name__ == "__main__":
  app.run(host='0.0.0.0', port=80)

應(yīng)用依賴:
定義在同目錄下的 requirements.txt 文件里,內(nèi)容如下:
[root@root ~]# vim requirements.txt
Flask
編寫Dockerfile

[root@qfedu.com ~]# 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文件說(shuō)明

FROM python:2.7-slim

使用官方提供的 Python 開發(fā)鏡像作為基礎(chǔ)鏡像

指定"python:2.7-slim"這個(gè)官方維護(hù)的基礎(chǔ)鏡像,從而免去安裝 Python 等語(yǔ)言環(huán)境的操作。否則,這一段就得這么寫了:

FROM ubuntu:latest

RUN apt-get update -y

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

WORKDIR /app

將工作目錄切換為 /app,意思是在這一句之后,Dockerfile 后面的操作都以這一句指定的 /app 目錄作為當(dāng)前目錄。

ADD . /app
將當(dāng)前目錄下的所有內(nèi)容復(fù)制到 /app 下,Dockerfile 里的原語(yǔ)并不都是指對(duì)容器內(nèi)部的操作。比如 ADD,指的是把當(dāng)前目錄(即 Dockerfile 所在的目錄)里的文件,復(fù)制到指定容器內(nèi)的目錄當(dāng)中。

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

使用 pip 命令安裝這個(gè)應(yīng)用所需要的依賴

EXPOSE 80 //允許外界訪問容器的 80 端口

ENV NAME World //設(shè)置環(huán)境變量

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

設(shè)置容器進(jìn)程為:python app.py,即:這個(gè) Python 應(yīng)用的啟動(dòng)命令

這里app.py 的實(shí)際路徑是 /app/app.py。CMD ["python", "app.py"] 等價(jià)于 "docker run python app.py"。

在使用 Dockerfile 時(shí),可能還會(huì)看到一個(gè)叫作 ENTRYPOINT 的原語(yǔ)。它和 CMD 都是 Docker 容器進(jìn)程啟動(dòng)所必需的參數(shù),完整執(zhí)行格式是:"ENTRYPOINT CMD"。

但是,默認(rèn),Docker 會(huì)提供一個(gè)隱含的 ENTRYPOINT,即:/bin/sh -c。所以,在不指定 ENTRYPOINT 時(shí),比如在這個(gè)例子里,實(shí)際上運(yùn)行在容器里的完整進(jìn)程是:/bin/sh -c "python app.py",即 CMD 的內(nèi)容就是 ENTRYPOINT 的參數(shù)。

基于以上原因,后面會(huì)統(tǒng)一稱 Docker 容器的啟動(dòng)進(jìn)程為 ENTRYPOINT,而不是 CMD。

/bin/bash -c 'pwd' 與pwd 結(jié)果一樣 完整的終端命令

現(xiàn)在目錄結(jié)構(gòu):

[root@qfedu.com ~]# ls
Dockerfile  app.py  requirements.txt

構(gòu)建鏡像

[root@qfedu.com ~]# docker build -t helloworld .
-t  給這個(gè)鏡像加一個(gè) Tag

Dockerfile 中的每個(gè)原語(yǔ)執(zhí)行后,都會(huì)生成一個(gè)對(duì)應(yīng)的鏡像層。即使原語(yǔ)本身并沒有明顯地修改文件的操作(比如,ENV 原語(yǔ)),它對(duì)應(yīng)的層也會(huì)存在。只不過在外界看來(lái),這個(gè)層是空的。

查看結(jié)果:
[root@root ~]# docker image ls

REPOSITORY       TAG             IMAGE ID
helloworld       latest        653287cdf998

啟動(dòng)容器

[root@root ~]# docker run -p 4000:80 helloworld 
鏡像名 helloworld 后面,什么都不用寫,因?yàn)樵?Dockerfile 中已經(jīng)指定了 CMD。
否則,就得把進(jìn)程的啟動(dòng)命令加在后面:
[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

進(jìn)入容器

[root@qfedu.com ~]# docker exec -it b69 /bin/bash

訪問容器內(nèi)應(yīng)用

[root@qfedu.com ~]# curl http://localhost:4000

結(jié)果如下:
<h3>Hello World!</h3><b>Hostname:</b> 4ddf4638572d

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容