版本
docker version
登录
docker login -u User -p Pasword <docker-server>
Docker会将token存储在~/.docker/config.json文件中,从而作为拉取私有镜像的凭证。
注销
docker logout <docker-server>
查询
docker images
搜索镜像
docker search image
拉取镜像
docker pull image:tag
docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
da7391352a9b: Pull complete
14428a6d4bcd: Pull complete
2c2d948710f2: Pull complete
Digest: sha256:c95a8e48bf88e9849f3e0f723d9f49fa12c5a00cfc6e60d2bc99d87555295e4c
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latest
sha256
摘要创建镜像
docker image build -t <image name>:<tag> .
.
表示上下文环境,Dockerfile 在当前路径查看镜像
# 列出所有镜像,不包含中间层镜像
docker images
# 或者
docker image ls
# 列出所有虚悬镜像
docker image ls -f dangling=true
# 列出所有镜像,包含中间层镜像
docker images -a
# 或者
docker image ls -a
# 列出指定镜像
docker images <image name>
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql 8.0 ab2f358b8612 10 days ago 545MB
说明:
<REPOSITORY>:<TAG>
来识别,也可以通过<IMAGE ID>
来识别注意:
无标签的镜像<none>
,与之前的虚空镜像不同,这些无标签的镜像很多都是中间层镜像,是其他镜像的依赖对象,只要删除了这些中间层镜像,这些依赖他们的镜像也将会被删除。
查看镜像的详细信息
docker inspect <image name>:<tag>
删除镜像
docker rmi <image name>:<tag>
# 或者
docker image rm <image name>:<tag>
# 删除所有镜像
docker rmi $(docker images -q)
# 或者
docker image prune -f -a
标签名缺省是latest,如果标签名是latest,则不用添加标签名
发布镜像
docker push <image name>:<tag>
容器的实质是进程,容器进程运行于属于自己的独立的命名空间。容器也是分层存储,每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层。
docker ps
# 或者
docker container ls
# 列出所有的容器文件(包括停止运行的容器)
docker ps -a
# 或者
docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f4e1e80e33c echo1:1.0 "/bin/sh -c 'echo us…" 55 minutes ago Exited (0) 55 minutes ago strange_mirzakhani
0094e5d008c9 mysql:8.0 "docker-entrypoint.s…" 4 days ago Exited (255) 4 days ago 33060/tcp, 0.0.0.0:3308->3306/tcp slave_mysql
174711ccb475 mysql:8.0 "docker-entrypoint.s…" 4 days ago Exited (255) 4 days ago 33060/tcp, 0.0.0.0:3307->3306/tcp master_mysql
类
和实例
一样,镜像是静态的定义,容器是运行时的实体运行容器
docker run -p 3307:3306 --name <container name> -d <image name>:<tag>
进入容器
docker exec -it <container ID>|<container name> /bin/bash
停止容器
docker stop <container ID>|<container name>
# 停止所有容器
docker stop $(docker ps -aq)
删除容器
docker rm <container ID>|<container name>
# 删除所有停止的容器
docker container prune
# 或者
docker rm $(docker ps -aq)
查询容器ip
docker inspect --format='{{.NetworkSettings.IPAddress}}' container_id|container_name
查看容器日志
docker logs -f <container ID>|<container name>
查看容器的详细信息
docker inspect <container ID>
复制文件
# docker -> local
docker cp <container ID>:/opt/file.txt /opt/local/
# local -> docker
docker cp /opt/local/file.txt <container ID>:/opt/
Dockerfile 中的每一条指令都会建立一个层,所以多条sh
指令最好使用&&
,;
等连接,这样生成的层会很少,镜像也会小很多。
FROM
开头ENTRYPOINT
,如果有多个以最后一个为准CMD
,如果有多个以最后一个为准Dockerfile
FROM alpine:latest as production
LABEL Author="feiquanxx@gmail.com"
RUN mkdir /lib64 &&
ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2 &&
echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories &&
echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories &&
apk add tzdata &&
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&
echo "Asia/Shanghai" > /etc/timezone &&
mkdir -p /app/ /config/
COPY ./bin/* /app/*
COPY ./config/* /config/
EXPOSE 8080
ENTRYPOINT ["/app/server","-c","/config/app.yaml"]
FROM 指定基础镜像为 alpine,版本为 latest,并重命名为production
LABEL 指定署名邮箱
RUN 指定在容器内执行的命令
# musl和glibc是兼容的,通过创建该符号链接修复缺少的依赖项,可以保证编译后 go 程序可以正常运行
mkdir /lib64
ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
# 更新源
echo "http://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories
echo "http://mirrors.aliyun.com/alpine/latest-stable/community/" >> /etc/apk/repositories
# 同步时间
apk add tzdata
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
echo "Asia/Shanghai" > /etc/timezone
# 创建项目目录
mkdir -p /app/ /config/
COPY 将当前本机上的文件复制到容器内指定位置
EXPOSE 容器将使用 8080 端口,这里只是声明并不会建立和本机的端口映射
ENTRYPOINT 容器启动时执行的命令
/app/server -c /config/app.yaml
FORM
基础镜像必须指定,FROM指令指定基础镜像,因此一个 Dockerfile 文件中 FROM 是必备指令,而且是第一个指令
FROM scratch
指定一个空白镜像,scratch 不以任何镜像为基础,接下来写的指令将作为镜像第一层开始存在
LABEL
添加元数据到镜像。LABEL
是以键值对形式出现的
RUN
在容器内执行指定命令
COPY
将本机构建上下文中的指定文件复制到镜像中
ADD
仅在需要自动解压缩的情况下才使用ADD指令,如果只是复制文件就使用COPY指令
ENV
设置容器的环境变量
ENV name=linux
EXPOSE
声明容器将要使用的端口,并不建立和主机的端口映射。当运行容器时使用-p
才是真正的建立端口映射
ENTRYPOINT
exec格式用法 [推荐]
程序入口点,执行docker run
命令时,设置的任何命令参数或CMD指令的命令,都将作为ENTRYPOINT指令的命令参数,追加到ENTRYPOINT指令的命令之后。
ENTRYPOINT ["top","-b","-H"]
如果此时创建docker 实例
docker run <container-name> -v
则实际执行的命令是 top -b -H -v
shell 格式用法
屏蔽追加任何参数,即CMD指令或docker run … 的参数都将被忽略。
ENTRYPOINT top -b -H
在创建容器后会首先调用Shell,即自动在命令前面追加/bin/sh -c
。既容器启动时,将执行/bin/sh -c top -b -H
。这样会导致top
命令就不是容器中的第一个进程PID 1,这样在容器停止的时候就无法收到系统的SIGTERM信号。要想收到SIGTERM信号,务必使用Bash的内置exec命令使得top的PID 1,定义ENTRYPOINT指令如下:
ENTRYPOINT exec top -b -H
CMD
用于指定默认的容器主进程的启动命令。
不同格式:
exec格式用法 [推荐]
参数追加模式,第一个参数必须是命令的全路径
如果docker run
没有指定任何的执行命令或参数,但是,dockerfile 中有CMD和ENTRYPOINT, 那么 CMD 中的全部内容将作为 ENTRYPOINT 的参数
FROM ubuntu:latest
CMD ["echo","username"]
ENTRYPOINT ["echo","ENTRYPOINT"]
# 构建
docker image build -t echo1:2.0 -f Dockerfile .
# 无参运行
docker run echo1:2.0 # 输出:ENTRYPOINT
# 带参数运行
docker run echo1:2.0 echo "test" # 输出:ENTRYPOINT echo test
输出变量:
FROM ubuntu:latest
ENV user=feiquan
# 这种写法无法输出变量,会直接输出 username:$user
# CMD ["username:$user"]
# ENTRYPOINT ["/bin/echo,"echo ENTRYPOINT:$user"]
CMD ["/bin/sh","-c","echo username:$user"]
ENTRYPOINT ["/bin/sh","-c","echo ENTRYPOINT:$user"]
# 构建
docker image build -t echo1:4.0 -f Dockerfile .
# 无参运行
docker run echo1:4.0 # 输出:ENTRYPOINT:feiquan
# 带参数运行
docker run echo1:4.0 docker run echo1:4.0 && echo "test:$user"
# 输出:
ENTRYPOINT:feiquan
test:
由于在传入&& echo "test:$user"
时,$user
使用的本机中环境变量,它为空,所以这里命令在追加后执行的其实是/bin/sh -c echo ENTRYPOINT:$user && echo "test:"
。
设置user=xx
后,再次执行输出:
ENTRYPOINT:feiquan
test:xx
shell 格式用法
屏蔽追加任何参数,即CMD指令或docker run … 的参数都将被忽略。在创建容器后会首先调用Shell,即自动在命令前面追加/bin/sh -c
。
如果docker run
没有指定任何的执行命令或者dockerfile里面也没有ENTRYPOINT,那么,就会使用cmd指定的默认的执行命令执行。
FROM ubuntu:latest
CMD echo username
# 构建
docker image build -t echo1:1.0 -f Dockerfile .
# 无参运行
docker run echo1:1.0 # 输出:username
# 带参数运行
docker run echo1:1.0 echo "test" # 输出:test
输出变量:
FROM ubuntu:latest
ENV user=feiquan
CMD echo username:$user
# 构建
docker image build -t echo1:3.0 -f Dockerfile .
# 无参运行
docker run echo1:3.0 # 输出:username:feiquan
# 带参数运行
docker run echo1:3.0 echo "test" # 输出:test
WORKDIR
指定工作目录,也就是启动容器后终端所在路径,默认~
。如果WORKDIR指 定的目录不存在,即使随后的指令没有用到这个目录,都会创建
VOLUME
实现数据的持久化,为了防止运行时用户忘记将动态文件所保存目录挂载为卷,在 Dockerfile 中,我们可以事先指定某些目录挂载为匿名卷,这样在运行时如果用户不指定挂载,其应用也可以正常运行,不会向容器存储层写入大量数据。
管理卷
# 创建一个自定义容器卷
docker volume create mdata
# 查看所有容器卷
docker volume ls
# 查看指定容器卷详情信息
docker volume inspect mdata
[
{
"CreatedAt": "2020-12-22T10:41:39Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/mdata/_data",
"Name": "mdata",
"Options": {},
"Scope": "local"
}
]
使用指定卷
FROM ubuntu:latest
VOLUME /data
RUN ls -ah / > /data/dir.txt
ENTRYPOINT sleep 10000
# 构建
docker image build -t echo1:5.0 -f Dockerfile .
# 挂载
docker run -d -v mdata:/data echo1:5.0
mdata
,并将其挂载到/data
进入容器查看:
docker exec -it 90177637380d /bin/bash
ls data
root@90177637380d:/# ll /data/
total 12
drwxr-xr-x 2 root root 4096 Dec 22 11:26 ./
drwxr-xr-x 1 root root 4096 Dec 22 11:12 ../
-rw-r--r-- 1 root root 119 Dec 22 11:10 dir.txt
本机查看
# mac 主机需要先执行
# screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
ll /var/lib/docker/volumes/mdata/_data
删除卷
docker volume rm <volume-name>