首页
关于
友链
Search
1
wlop 4K 壁纸 4k8k 动态 壁纸
1,467 阅读
2
Nacos持久化MySQL问题-解决方案
931 阅读
3
Docker搭建Typecho博客
749 阅读
4
滑动时间窗口算法
728 阅读
5
Nginx反向代理微服务配置
699 阅读
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
登录
Search
标签搜索
java
javase
docker
java8
springboot
thread
spring
分布式
mysql
锁
linux
redis
源码
typecho
centos
git
map
RabbitMQ
lambda
stream
少年
累计撰写
189
篇文章
累计收到
24
条评论
首页
栏目
生活
解决方案
JAVA基础
JVM
多线程
开源框架
数据库
前端
分布式
框架整合
中间件
容器部署
设计模式
数据结构与算法
安全
开发工具
百度网盘
天翼网盘
阿里网盘
页面
关于
友链
搜索到
4
篇与
的结果
2023-05-10
Docker数据存储
Docker数据存储默认情况下,在运行中的容器里创建的文件,被保存在一个可写的容器层:如果容器被删除了,则数据也没有了这个可写的容器层是和特定的容器绑定的,也就是这些数据无法方便的和其它容器共享Docker主要提供了两种方式做数据的持久化Data Volume, 由Docker管理,(/var/lib/docker/volumes/ Linux), 持久化数据的最好方式Bind Mount,由用户指定存储的数据具体mount在系统什么位置一、Data Volume环境准备准备一个Dockerfile 和一个 my-cron的文件$ ls Dockerfile my-cron $ more Dockerfile FROM alpine:latest RUN apk update RUN apk --no-cache add curl ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \ SUPERCRONIC=supercronic-linux-amd64 \ SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e RUN curl -fsSLO "$SUPERCRONIC_URL" \ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ && chmod +x "$SUPERCRONIC" \ && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic COPY my-cron /app/my-cron WORKDIR /app VOLUME ["/app"] # RUN cron job CMD ["/usr/local/bin/supercronic", "/app/my-cron"] $ $ more my-cron */1 * * * * date >> /app/test.txt构建镜像$ docker image build -t my-cron . $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE my-cron latest e9fbd9a562c9 4 seconds ago 24.7MB创建容器(不指定-v参数)此时Docker会自动创建一个随机名字的volume,去存储我们在Dockerfile定义的volume VOLUME ["/app"]$ docker run -d my-cron 9a8fa93f03c42427a498b21ac520660752122e20bcdbf939661646f71d277f8f $ docker volume ls DRIVER VOLUME NAME local 043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264 $ docker volume inspect 043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264 [ { "CreatedAt": "2021-06-22T23:06:13+02:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264/_data", "Name": "043a196c21202c484c69f2098b6b9ec22b9a9e4e4bb8d4f55a4c3dce13c15264", "Options": null, "Scope": "local" } ]在这个Volume的mountpoint可以发现容器创建的文件。创建容器(指定-v参数)在创建容器的时候通过 -v 参数我们可以手动的指定需要创建Volume的名字,以及对应于容器内的路径,这个路径是可以任意的,不必需要在Dockerfile里通过VOLUME定义。比如我们把上面的Dockerfile里的VOLUME删除FROM alpine:latest RUN apk update RUN apk --no-cache add curl ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \ SUPERCRONIC=supercronic-linux-amd64 \ SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e RUN curl -fsSLO "$SUPERCRONIC_URL" \ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \ && chmod +x "$SUPERCRONIC" \ && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \ && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic COPY my-cron /app/my-cron WORKDIR /app # RUN cron job CMD ["/usr/local/bin/supercronic", "/app/my-cron"]重新build镜像,然后创建容器,加-v参数$ docker image build -t my-cron . $ docker container run -d -v cron-data:/app my-cron 43c6d0357b0893861092a752c61ab01bdfa62ea766d01d2fcb8b3ecb6c88b3de $ docker volume ls DRIVER VOLUME NAME local cron-data $ docker volume inspect cron-data [ { "CreatedAt": "2021-06-22T23:25:02+02:00", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/cron-data/_data", "Name": "cron-data", "Options": null, "Scope": "local" } ] $ ls /var/lib/docker/volumes/cron-data/_data my-cron $ ls /var/lib/docker/volumes/cron-data/_data my-cron test.txt环境清理强制删除所有容器,系统清理和volume清理$ docker rm -f $(docker container ps -aq) $ docker system prune -f $ docker volume prune -f二、Bind Mount只需要将-v的data volume换成指定路径即可。windows下的linux就可以直接挂载到磁盘,linx的可以直接查看。例如mysqldocker run -p 3306:3306 --name mysql \ -v /mydata/mysql/log:/var/log/mysql \ -v /mydata/mysql/data:/var/lib/mysql \ -v /mydata/mysql/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD=密码 \ -d mysql:5.7-v /mydata/mysql/log:/var/log/mysql这里就是将容器中/var/log/mysql日志,通过Bind Mount持久化到linux主机的/mydata/mysql/log目录。多个机器之间的容器共享数据官方参考链接 https://docs.docker.com/storage/volumes/#share-data-among-machinesDocker的volume支持多种driver。默认创建的volume driver都是local$ docker volume inspect vscode [ { "CreatedAt": "2021-06-23T21:33:57Z", "Driver": "local", "Labels": null, "Mountpoint": "/var/lib/docker/volumes/vscode/_data", "Name": "vscode", "Options": null, "Scope": "local" } ]这一节我们看看一个叫sshfs的driver,如何让docker使用不在同一台机器上的文件系统做volume环境准备准备三台Linux机器,之间可以通过SSH相互通信。hostnameipssh usernamessh passworddocker-host1192.168.200.10vagrantvagrantdocker-host2192.168.200.11vagrantvagrantdocker-host3192.168.200.12vagrantvagrant安装plugin在其中两台机器上安装一个plugin vieux/sshfs[vagrant@docker-host1 ~]$ docker plugin install --grant-all-permissions vieux/sshfs latest: Pulling from vieux/sshfs Digest: sha256:1d3c3e42c12138da5ef7873b97f7f32cf99fb6edde75fa4f0bcf9ed277855811 52d435ada6a4: Complete Installed plugin vieux/sshfs[vagrant@docker-host2 ~]$ docker plugin install --grant-all-permissions vieux/sshfs latest: Pulling from vieux/sshfs Digest: sha256:1d3c3e42c12138da5ef7873b97f7f32cf99fb6edde75fa4f0bcf9ed277855811 52d435ada6a4: Complete Installed plugin vieux/sshfs创建volume[vagrant@docker-host1 ~]$ docker volume create --driver vieux/sshfs \ -o sshcmd=vagrant@192.168.200.12:/home/vagrant \ -o password=vagrant \ sshvolume查看[vagrant@docker-host1 ~]$ docker volume ls DRIVER VOLUME NAME vieux/sshfs:latest sshvolume [vagrant@docker-host1 ~]$ docker volume inspect sshvolume [ { "CreatedAt": "0001-01-01T00:00:00Z", "Driver": "vieux/sshfs:latest", "Labels": {}, "Mountpoint": "/mnt/volumes/f59e848643f73d73a21b881486d55b33", "Name": "sshvolume", "Options": { "password": "vagrant", "sshcmd": "vagrant@192.168.200.12:/home/vagrant" }, "Scope": "local" } ]创建容器挂载Volume创建容器,挂载sshvolume到/app目录,然后进入容器的shell,在/app目录创建一个test.txt文件[vagrant@docker-host1 ~]$ docker run -it -v sshvolume:/app busybox sh Unable to find image 'busybox:latest' locally latest: Pulling from library/busybox b71f96345d44: Pull complete Digest: sha256:930490f97e5b921535c153e0e7110d251134cc4b72bbb8133c6a5065cc68580d Status: Downloaded newer image for busybox:latest / # / # ls app bin dev etc home proc root sys tmp usr var / # cd /app /app # ls /app # echo "this is ssh volume"> test.txt /app # ls test.txt /app # more test.txt this is ssh volume /app # /app #这个文件我们可以在docker-host3上看到[vagrant@docker-host3 ~]$ pwd /home/vagrant [vagrant@docker-host3 ~]$ ls test.txt [vagrant@docker-host3 ~]$ more test.txt this is ssh volume
2023年05月10日
160 阅读
1 评论
2 点赞
2023-04-25
Dockerfile使用技巧
Dockerfile技巧一、Docker build缓存当build镜像时,如果Docker build文件发生变化或者build镜像分层某一层发生变化就不会使用cache缓存。技巧:将Dockerfile中经常发生改变的放到后面,不发生改变的发前面。这样就算最后发生改变的不能使用cache缓存,但前面没变化也会加快build的速度。Docker build contextDocker是client-server架构,理论上Client和Server可以不在一台机器上。在构建docker镜像的时候,需要把所需要的文件由CLI(client)发给Server,这些文件实际上就是build context。$ dockerfile-demo more Dockerfile FROM python:3.9.5-slim RUN pip install flask WORKDIR /src ENV FLASK_APP=app.py COPY app.py /src/app.py EXPOSE 5000 CMD ["flask", "run", "-h", "0.0.0.0"] $ dockerfile-demo more app.py from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, world!'执行镜像构建$ docker image build -t demo . Sending build context to Docker daemon 11.13MB Step 1/7 : FROM python:3.9.5-slim ---> 609da079b03a Step 2/7 : RUN pip install flask ---> Using cache ---> 955ce495635e Step 3/7 : WORKDIR /src ---> Using cache ---> 1c2f968e9f9b Step 4/7 : ENV FLASK_APP=app.py ---> Using cache ---> dceb15b338cf Step 5/7 : COPY app.py /src/app.py ---> Using cache ---> 0d4dfef28b5f Step 6/7 : EXPOSE 5000 ---> Using cache ---> 203e9865f0d9 Step 7/7 : CMD ["flask", "run", "-h", "0.0.0.0"] ---> Using cache ---> 35b5efae1293 Successfully built 35b5efae1293 Successfully tagged demo:latest. 这个参数就是代表了build context所指向的目录。第2行:Sending build context to Docker daemon 11.13MB,实际就是docker build context将.所指向文件夹里面所有的文件发送到Docker Server。因此当文件里面文件很多时,发送就比较大比较慢,所以进行保证指向的文件夹里面文件少一点。二、.dockerignore 文件配置需要忽略的文件,类似git里面.ignore文件一样。1、可以使image变小一点。2、加快build。3、忽略一些私密配置文件,如密码配置等。.vscode/ env/$ docker image build -t demo . Sending build context to Docker daemon 4.096kB Step 1/7 : FROM python:3.9.5-slim ---> 609da079b03a Step 2/7 : RUN pip install flask ---> Using cache ---> 955ce495635e Step 3/7 : WORKDIR /src ---> Using cache ---> 1c2f968e9f9b Step 4/7 : ENV FLASK_APP=app.py ---> Using cache ---> dceb15b338cf Step 5/7 : COPY . /src/ ---> a9a8f888fef3 Step 6/7 : EXPOSE 5000 ---> Running in c71f34d32009 Removing intermediate container c71f34d32009 ---> fed6995d5a83 Step 7/7 : CMD ["flask", "run", "-h", "0.0.0.0"] ---> Running in 7ea669f59d5e Removing intermediate container 7ea669f59d5e ---> 079bae887a47 Successfully built 079bae887a47 Successfully tagged demo:latest上面可以看到Sending build context to Docker daemon 4.096kB,从这里可以看到Docker build context忽略文件后,发送到docker server的文件变小了很多。三、镜像的多阶段构建适用于需要环境进行编译时。例如要将C语言程序build成一个镜像,然后通过docker容器执行。#include <stdio.h> void main(int argc, char *argv[]) { printf("hello %s\n", argv[argc - 1]); }docker build:因为需要C语言环境,因此选择一个gcc基础镜像,可以看到gcc基础环境比较到,c文件其实很小。FROM gcc:9.4 COPY hello.c /src/hello.c WORKDIR /src RUN gcc --static -o hello hello.c ENTRYPOINT [ "/src/hello" ] CMD []build和测试$ docker build -t hello . Sending build context to Docker daemon 5.12kB Step 1/6 : FROM gcc:9.4 ---> be1d0d9ce039 Step 2/6 : COPY hello.c /src/hello.c ---> Using cache ---> 70a624e3749b Step 3/6 : WORKDIR /src ---> Using cache ---> 24e248c6b27c Step 4/6 : RUN gcc --static -o hello hello.c ---> Using cache ---> db8ae7b42aff Step 5/6 : ENTRYPOINT [ "/src/hello" ] ---> Using cache ---> 7f307354ee45 Step 6/6 : CMD [] ---> Using cache ---> 7cfa0cbe4e2a Successfully built 7cfa0cbe4e2a Successfully tagged hello:latest $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 7cfa0cbe4e2a 2 hours ago 1.14GB gcc 9.4 be1d0d9ce039 9 days ago 1.14GB $ docker run --rm -it hello docker hello docker $ docker run --rm -it hello world hello world $ docker run --rm -it hello friends hello friends $gcc 9.4 be1d0d9ce039 9 days ago 1.14GB实际上当我们把hello.c编译完以后,并不需要这样一个大的GCC环境,一个小的alpine镜像就可以了。因此就可以使用多阶段构建。FROM gcc:9.4 AS builder COPY hello.c /src/hello.c WORKDIR /src RUN gcc --static -o hello hello.c FROM alpine:3.13.5 COPY --from=builder /src/hello /src/hello ENTRYPOINT [ "/src/hello" ] CMD []说明:AS 给gcc取一个名称builder,第2阶段COPY --from=builder /src/hello /src/hello,将编译好的c程序,放到新基础镜像alpine中,重新build成镜像。测试$ docker build -t hello-apline -f Dockerfile-new . Sending build context to Docker daemon 5.12kB Step 1/8 : FROM gcc:9.4 AS builder ---> be1d0d9ce039 Step 2/8 : COPY hello.c /src/hello.c ---> Using cache ---> 70a624e3749b Step 3/8 : WORKDIR /src ---> Using cache ---> 24e248c6b27c Step 4/8 : RUN gcc --static -o hello hello.c ---> Using cache ---> db8ae7b42aff Step 5/8 : FROM alpine:3.13.5 ---> 6dbb9cc54074 Step 6/8 : COPY --from=builder /src/hello /src/hello ---> Using cache ---> 18c2bce629fb Step 7/8 : ENTRYPOINT [ "/src/hello" ] ---> Using cache ---> 8dfb9d9d6010 Step 8/8 : CMD [] ---> Using cache ---> 446baf852214 Successfully built 446baf852214 Successfully tagged hello-apline:latest $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE hello-alpine latest 446baf852214 2 hours ago 6.55MB hello latest 7cfa0cbe4e2a 2 hours ago 1.14GB demo latest 079bae887a47 2 hours ago 125MB gcc 9.4 be1d0d9ce039 9 days ago 1.14GB $ docker run --rm -it hello-alpine docker hello docker $ docker run --rm -it hello-alpine world hello world $ docker run --rm -it hello-alpine friends hello friends $Sending build context to Docker daemon 5.12kB 可以看到这个镜像非常小,只有6.55MB。四、尽量使用非root用户Root的危险性假如我们有一个用户,叫demo,它本身不具有sudo的权限,所以就有很多文件无法进行读写操作,比如/root目录它是无法查看的。但是有执行docker容器的权限,可以映射root文件路径,查看root文件。[demo@docker-host ~]$ sudo ls /root [sudo] password for demo: demo is not in the sudoers file. This incident will be reported. [demo@docker-host ~]$但是这个用户有执行docker的权限,也就是它在docker这个group里。[demo@docker-host ~]$ groups demo docker [demo@docker-host ~]$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE busybox latest a9d583973f65 2 days ago 1.23MB [demo@docker-host ~]$这时,我们就可以通过Docker做很多越权的事情了,比如,我们可以把这个无法查看的/root目录映射到docker container里,你就可以自由进行查看了。[demo@docker-host vagrant]$ docker run -it -v /root/:/root/tmp busybox sh / # cd /root/tmp ~/tmp # ls anaconda-ks.cfg original-ks.cfg ~/tmp # ls -l total 16 -rw------- 1 root root 5570 Apr 30 2020 anaconda-ks.cfg -rw------- 1 root root 5300 Apr 30 2020 original-ks.cfg ~/tmp #更甚至我们可以给我们自己加sudo权限。我们现在没有sudo权限。[demo@docker-host ~]$ sudo vim /etc/sudoers [sudo] password for demo: demo is not in the sudoers file. This incident will be reported. [demo@docker-host ~]$但是我可以给自己添加。[demo@docker-host ~]$ docker run -it -v /etc/sudoers:/root/sudoers busybox sh / # echo "demo ALL=(ALL) ALL" >> /root/sudoers / # more /root/sudoers | grep demo demo ALL=(ALL) ALL然后退出container,bingo,我们有sudo权限了。[demo@docker-host ~]$ sudo more /etc/sudoers | grep demo demo ALL=(ALL) ALL [demo@docker-host ~]$如何使用非root用户我们准备两个Dockerfile,第一个Dockerfile如下,其中app.py文件源码:FROM python:3.9.5-slim RUN pip install flask COPY app.py /src/app.py WORKDIR /src ENV FLASK_APP=app.py EXPOSE 5000 CMD ["flask", "run", "-h", "0.0.0.0"]假设构建的镜像名字为 flask-demo第二个Dockerfile,使用非root用户来构建这个镜像,名字叫 flask-no-root Dockerfile如下:通过groupadd和useradd创建一个flask的组和用户通过USER指定后面的命令要以flask这个用户的身份运行FROM python:3.9.5-slim RUN pip install flask && \ groupadd -r flask && useradd -r -g flask flask && \ mkdir /src && \ chown -R flask:flask /src USER flask COPY app.py /src/app.py WORKDIR /src ENV FLASK_APP=app.py EXPOSE 5000 CMD ["flask", "run", "-h", "0.0.0.0"]$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE flask-no-root latest 80996843356e 41 minutes ago 126MB flask-demo latest 2696c68b51ce 49 minutes ago 125MB python 3.9.5-slim 609da079b03a 2 weeks ago 115MB分别使用这两个镜像创建两个容器$ docker run -d --name flask-root flask-demo b31588bae216951e7981ce14290d74d377eef477f71e1506b17ee505d7994774 $ docker run -d --name flask-no-root flask-no-root 83aaa4a116608ec98afff2a142392119b7efe53617db213e8c7276ab0ae0aaa0 $ docker container ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 83aaa4a11660 flask-no-root "flask run -h 0.0.0.0" 4 seconds ago Up 3 seconds 5000/tcp flask-no-root b31588bae216 flask-demo "flask run -h 0.0.0.0" 16 seconds ago Up 15 seconds 5000/tcp flask-root
2023年04月25日
158 阅读
0 评论
0 点赞
2023-04-16
Dockerfile
基础镜像的选择 (FROM)官方镜像优于非官方的镜像,如果没有官方镜像,则尽量选择Dockerfile开源的固定版本tag而不是每次都使用latest尽量选择体积小的镜像空镜像:scratch最小镜像:alpine通过 RUN 执行指令RUN 主要用于在Image里执行指令,比如安装软件,下载文件等。FROM ubuntu:20.04 RUN apt-get update RUN apt-get install -y wget RUN wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz RUN tar zxf ipinfo_2.0.1_linux_amd64.tar.gz RUN mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo RUN rm -rf ipinfo_2.0.1_linux_amd64.tar.gz每执行一次RUN执行,就会新产生一个分层。一般使用,优化后的执行命令:FROM ubuntu:20.04 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz && \ tar zxf ipinfo_2.0.1_linux_amd64.tar.gz && \ mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_2.0.1_linux_amd64.tar.gz&&:指令拼接\:命令换行。只执行了一次RUN,则只会产生一个分层。文件复制和目录操作(ADD,COPY,WORKDIR)往镜像里复制文件有两种方式,COPY 和 ADD , 我们来看一下两者的不同。复制普通文件COPY 和 ADD 都可以把local的一个文件复制到镜像里,如果目标目录不存在,则会自动创建。FROM python:3.9.5-alpine3.13 COPY hello.py /app/hello.py比如把本地的 hello.py 复制到 /app 目录下。 /app这个folder不存在,则会自动创建。复制压缩文件ADD 比 COPY高级一点的地方就是,如果复制的是一个gzip等压缩文件时,ADD会帮助我们自动去解压缩文件。FROM python:3.9.5-alpine3.13 ADD hello.tar.gz /app/所有的文件复制均使用 COPY 指令,仅在需要自动解压缩的场合使用 ADD。注意:对应文件的权限复制到基础镜像里面后权限一样。目录切换WORKDIR:目录切换,类似cd的操作。比cd好的是,没有目录时,会帮自动创建。FROM python:3.9.5-alpine3.13 WORKDIR /app COPY hello.py hello.pyWORKDIR切换目录后,copy默认copy到切换后的app目录下。构建参数和环境变量 (ARG vs ENV)ARG 和 ENV 是经常容易被混淆的两个Dockerfile的语法,都可以用来设置一个“变量”。 但实际上两者有很多的不同。例子:安装某个特定版本软件时,需要对版本进行升级,就可以定义参数变量,方便后续升级,直接改版本号即可。FROM ubuntu:20.04 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-2.0.1/ipinfo_2.0.1_linux_amd64.tar.gz && \ tar zxf ipinfo_2.0.1_linux_amd64.tar.gz && \ mv ipinfo_2.0.1_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_2.0.1_linux_amd64.tar.gz上面是没有使用变量时,每次升级就需要改版本号2.0.1,这样会修改很多地方,这时就可以定义参数变量,之后升级改一个地方就可以了。ENV变量FROM ubuntu:20.04 ENV VERSION=2.0.1 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \ tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \ mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_${VERSION}_linux_amd64.tar.gzARG变量FROM ubuntu:20.04 ARG VERSION=2.0.1 RUN apt-get update && \ apt-get install -y wget && \ wget https://github.com/ipinfo/cli/releases/download/ipinfo-${VERSION}/ipinfo_${VERSION}_linux_amd64.tar.gz && \ tar zxf ipinfo_${VERSION}_linux_amd64.tar.gz && \ mv ipinfo_${VERSION}_linux_amd64 /usr/bin/ipinfo && \ rm -rf ipinfo_${VERSION}_linux_amd64.tar.gz使用时,都是${变量名}这样使用。如果要改版本,这样直接改VERSION=新版本号就可以了。ENV与ARG区别ARG:只作用域镜像构建过程中,镜像环境中是没有该参数的,后续容器中不能使用改参数变量。build镜像时可以使用参数--build-arg动态改变参数值。例如:docker image build -f .\Dockerfile-arg -t ipinfo-arg-2.0.0 --build-arg VERSION=2.0.0 .ENV:会将参数设置到镜像中,通过env可以看到环境变量中有对应的参数,后续容器中也可以使用这些参数变量。不能动态改值。使用场景ARG主要用于关注build镜像的过程。ENV主要用于后续容器中使用。容器启动时默认执行的命令 CMDCMD可以用来设置容器启动时默认会执行的命令。容器启动时默认执行的命令如果docker container run启动容器时指定了其它命令,则CMD命令会被忽略如果定义了多个CMD,只有最后一个会被执行。1、清理后台已经停止的全部容器:docker system prune -f也可以一个一个清理docekr container rm 容器名称2、删除没有用到的全部镜像docker image prune -a当没有定义CMD命令时,会默认进入到shell是因为在ubuntu的基础镜像里有定义CMD。如果想一次行运行容器,运行完后自动删除容器:只需要在运行容器时加参数--rm即可。容器启动命令 ENTRYPOINTENTRYPOINT 也可以设置容器启动时要执行的命令,但是和CMD是有区别的。CMD 设置的命令,可以在docker container run 时传入其它命令,覆盖掉 CMD 的命令,但是 ENTRYPOINT 所设置的命令是一定会被执行的。ENTRYPOINT 和 CMD 可以联合使用,ENTRYPOINT 设置执行的命令,CMD传递参数。1、CMD命令的Dockerfile,build成一个叫 demo-cmd 的镜象。FROM ubuntu:20.04 CMD ["echo", "hello docker"]2、ENTRYPOINT命令的Dockerfile,build成一个叫 demo-entrypoint 的镜象。FROM ubuntu:20.04 ENTRYPOINT ["echo", "hello docker"]比较:CMD的镜像,如果执行创建容器,不指定运行时的命令,则会默认执行CMD所定义的命令,打印出hello docker$ docker container run -it --rm demo-cmd hello docker如果我们docker container run的时候指定命令,则该命令会覆盖掉CMD的命令:$ docker container run -it --rm demo-cmd echo "hello world" hello worldENTRYPOINT的容器里ENTRYPOINT所定义的命令则无法覆盖,一定会执行:$ docker container run -it --rm demo-entrypoint hello docker $ docker container run -it --rm demo-entrypoint echo "hello world" hello docker echo hello world会将echo "hello world"当作参数传入。3、CMD作为参数参数传入ENTRYPOINT,Dockerfile如下:FROM ubuntu:21.04 ENTRYPOINT ["echo"] CMD []将3编译成叫demoboth的镜像。docker run --rm -it demoboth不加cmd执行:执行echo打印了空行[root@10 ~]# docker run --rm -it demoboth:1.0 加cmd传入作为echo的参数打出:[root@10 ~]# docker run --rm -it demoboth:1.0 echo "hi docker" echo hi dockerShell 格式和 Exec 格式Shell格式CMD echo "hello docker"ENTRYPOINT echo "hello docker"Exec格式以可执行命令的方式ENTRYPOINT ["echo", "hello docker"]CMD ["echo", "hello docker"]注意shell脚本的问题FROM ubuntu:20.04 ENV NAME=docker CMD echo "hello $NAME"假如我们要把上面的CMD改成Exec格式,下面这样改是不行的。FROM ubuntu:20.04 ENV NAME=docker CMD ["echo", "hello $NAME"]它会打印出 hello $NAME , 而不是 hello docker ,那么需要怎么写呢? 我们需要以shell脚本的方式去执行:FROM ubuntu:20.04 ENV NAME=docker CMD ["sh", "-c", "echo hello $NAME"]"sh":执行sh命令“-c”: 执行的命令
2023年04月16日
186 阅读
0 评论
4 点赞
2023-04-08
Docker镜像创建、镜像push
镜像创建、镜像push是什么Dockerfile是用于构建docker镜像的文件Dockerfile里包括了构建镜像所需的“指令”Dockerfile有其特定的语法规则基本结构例如:在一台ubuntu 21.04上运行下面这个hello.py的Python程序不用daocker步骤:1、编写hello.py文件。print("hello docker")2、准备Python环境apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y python3.9 python3-pip python3.9-dev3、运行hello.py$ python3 hello.py hello docker使用Dockerfile构建镜像后就这样FROM ubuntu:20.04 RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y python3.9 python3-pip python3.9-dev ADD hello.py / CMD ["python3", "/hello.py"]说明:FROM:导入一个基础镜像RUN:要运行的linx命令ADD:添加文件到docker镜像的指定目录CMD:使用该镜像创建容器的时候,要执行的命令。构建镜像将写好的hello.py文件和Dockerfile文件放在一起进入该目录。构建镜像docker image build -t 容器名称:版本 构建镜像存放路径例如:docker image build -t hello .注意:如果不写版本号默认是latest。t:表示标签例如,构建上面的py镜像:docker image build -t i2cn/hello:1.0 .构建镜像名称是hell,版本默认是latest,存放位置当前文件夹下。注意:因为是根据一个image创建的,image的id是相同。镜像提交到DockerHub需要符合DockerHub命名规范。根据现有image修改tag生成一个新image tag:docker image tag 容器名称 新容器名称/名称:版本docker image tag i2cn/hello:1.0 i2cn/hello:1.1.0登录DockerHhub:docker login会提示输入用户名密码。推送自定义镜像到DockerHubdocker image push 镜像名称:tag注意:如果是要推送到自己的DockerHub一定要取一个自己账号开头的镜像名称。例如推送上面自己构建的镜像:docker image push i2cn/hello:1.0打开Docker hub自己仓库,就可以看到push的镜像了。测试拉去push的镜像删除本地镜像:docker image rm i2cn/hello:1.0从新拉取推送到dockerhub的镜像docker image pull i2cn/hello:1.0执行镜像:docker container run -it i2cn/hello:1.0可以看到输出:hello docker测试成功。commit创建镜像将现有容器的改变,commit成一个新的镜像。例如:启动一个nginx容器,修改nginx的欢迎页面信息,然后重新commit成一个新的镜像,如果要使用改变后的nginx容器,则可以直接执行commiit后的镜像即可。执行nginx镜像,运行nginx容器,查看nginx首页。docker container run -d -p 80:80 nginx进入nginx修改首页信息docker exec -it 8872c sh进入nginx容器首页文件路径cd /usr/share/nginx/html修改首页信息echo "<h1>hello word </h1>" > index.html用echo命令,将“hello word ”写入index.html查看首页信息重点:使用commit命令,将修改后的nginx容器,commit成一个镜像。停止nginx容器运行docker container stop 8872ccommit容器成一个新镜像:docker container commit 8872 i2cn/nginx:1.0.0查看通过commit新生成的镜像:创建容器,commit创建镜像1、创建ubuntu容器docker container run -it ubuntu:21.04 sh2、在ubuntu容器里面安装Python环境apt-get update && \ DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y python3.9 python3-pip python3.9-dev3、创建hello.py文件,打印hello dockerecho "print('hello docker')" > /hello.py4、推出ubuntu容器,通过commit打包ubuntu容器。docker container commit ubuntu i2cn/pydemo:1.05、通过打包后的pydemo:1.0镜像运行容器。docker container run i2cn/pydemo:1.0 python3 /hello.py 这种方法和离线导入导出不怎么使用。查看镜像分层docker image history 镜像名称例如查看nginx分层信息docker image history nginxscratch特殊镜像scratch镜像是一个为空的基础镜像。
2023年04月08日
151 阅读
0 评论
1 点赞