关于docker的scratch镜像与helloworld
参考:https://hub.docker.com/_/scratch?tab=descriptionhtml
参考:https://segmentfault.com/a/1190000000628247linux
FROM scratchgit
官方说明:该镜像是一个空的镜像,能够用于构建busybox等超小镜像,能够说是真正的从零开始构建属于本身的镜像。要知道,一个官方的ubuntu镜像有60MB+,CentOS镜像有70MB+github
能够把一个可执行文件扔进来直接执行golang
1、注意:scratch不可用被pull
FROM scratch专门用于构建最小镜像,直接pull会报如下错误,scratch是一个保留名称docker
[root@es-master1 ~]# docker pull scratch Using default tag: latest Error response from daemon: 'scratch' is a reserved name
2、如何制做大小为0 的镜像
既然scratch不能被拉取,如何作到docker image ls
看到一个0字节的镜像ubuntu
官方给出了下面方法:segmentfault
$ tar cv --files-from /dev/null | docker import - scratch $ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE scratch latest 775bfce21429 9 minutes ago 0B
3、如何跑一个helloworld
能够参考:https://github.com/docker-library/hello-world/bash
3.1C语言不行,docker是go语言写的,跑的话报错
[root@es-master1 ~]# cat hello.c #include <stdio.h> main() { printf("hello world\n"); }
[root@es-master1 ~]# gcc hello.c -o hello [root@es-master1 ~]# ll hello -rwxr-xr-x 1 root root 8440 Nov 21 03:36 hello
Dockerfileapp
FROM scratch COPY hello / CMD ["/hello"]
[root@es-master1 ~]# docker build -t hello . [root@es-master1 ~]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 3b89b5056a03 5 minutes ago 8.44kB
果真报错
[root@es-master1 ~]# docker run --rm hello standard_init_linux.go:211: exec user process caused "no such file or directory"
ubuntu固然能够
[root@es-master1 ~]# cat Dockerfile FROM ubuntu COPY hello / CMD ["/hello"] [root@es-master1 ~]# docker build -t hello . Sending build context to Docker daemon 24.63MB Step 1/3 : FROM ubuntu ---> 775349758637 Step 2/3 : COPY hello / ---> 33de2082f11a Step 3/3 : CMD ["/hello"] ---> Running in 3d347f62b926 Removing intermediate container 3d347f62b926 ---> 1829a7bd40fe Successfully built 1829a7bd40fe Successfully tagged hello:latest [root@es-master1 ~]# docker run --rm hello hello world
官方的这个居然有点看不懂了,c语言:https://github.com/docker-library/hello-world
[root@es-master1 tmp]# git clone https://github.com/docker-library/hello-world.git [root@es-master1 tmp]# cd hello-world/ [root@es-master1 hello-world]# make all [root@es-master1 hello-world]# amd64/hello-world/hello Hello from Docker! ......
3.2go语言
使用go语言写:https://github.com/adriaandejonge/helloworld
[root@es-master1 hello-world]# tree -C . . ├── Dockerfile └── hello.go 0 directories, 2 files
[root@es-master1 hello-world]# cat hello.go package main import "fmt" func main(){ fmt.Printf("hello world\n") }
[root@es-master1 hello-world]# cat Dockerfile FROM google/golang as builder WORKDIR /go/src/app COPY hello.go . RUN go build hello.go FROM scratch COPY --from=builder /go/src/app/hello / CMD ["/hello"]
一个helloworld都这么大...
[root@es-master1 hello-world]# docker build -t hello . [root@es-master1 hello-world]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 27eca431407a 2 minutes ago 2.36MB [root@es-master1 hello-world]# docker run --rm hello hello world
[root@es-master1 hello-world]# docker image history hello IMAGE CREATED CREATED BY SIZE COMMENT 27eca431407a 3 minutes ago /bin/sh -c #(nop) CMD ["/hello"] 0B 1a35249e8575 3 minutes ago /bin/sh -c #(nop) COPY file:7b1994197d7b5310… 2.36MB
也没用过go,网上了解到加个选项就能变小:https://www.jianshu.com/p/1405b0c2c5a3
[root@es-master1 hello-world]# cat Dockerfile FROM google/golang as builder WORKDIR /go/src/app COPY hello.go . RUN go build -ldflags="-w -s" hello.go FROM scratch COPY --from=builder /go/src/app/hello / CMD ["/hello"] [root@es-master1 hello-world]# docker build -t hello . [root@es-master1 hello-world]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest df8b3c8897f9 8 seconds ago 1.65MB
3.3改写官方的helloword
hello.c
[root@es-master1 ~]# cat hello.c //#include <unistd.h> #include <sys/syscall.h> #ifndef DOCKER_GREETING #define DOCKER_GREETING "Hello from Docker!" #endif const char message[] = DOCKER_GREETING "\n"; void _start() { //write(1, message, sizeof(message) - 1); syscall(SYS_write, 1, message, sizeof(message) - 1); //_exit(0); syscall(SYS_exit, 0); }
编译
[root@es-master1 ~]# gcc -static -Os -nostartfiles -fno-asynchronous-unwind-tables -o './hello' 'hello.c' [root@es-master1 ~]# strip -R .comment -s 'hello' [root@es-master1 ~]# ./hello Hello from Docker!
dockerfile
FROM scratch COPY hello / CMD ["/hello"]
[root@es-master1 ~]# docker build -t hello . #才1.06kB [root@es-master1 ~]# docker image ls hello REPOSITORY TAG IMAGE ID CREATED SIZE hello latest 3b204a40c8cb 14 seconds ago 1.06kB [root@es-master1 ~]# docker run --rm hello Hello from Docker!
4、补充
- gcc -D能够定义宏,起到替换、条件编译的功能;即hello.c中定义了一个宏,我能够在gcc编译时使用-D替换该宏。就好像我docker镜像定义了一些变量,可是docker run仍能够-e传递变量,覆盖原有的变量
- gcc -static指定强制使用静态库,
- -O 对程序进行优化编译、连接。采用这个选项,整个源代码会在编译、连接过程当中进行优化处理,这样产生的可执行文件的执行效率能够提升,可是编译、连接的速度就相应地要慢一些,并且对执行文件的调试会产生必定的影响,形成一些执行效果与对应源文件代码不一致等一些使人“困惑”的状况。所以,通常在编译输出软件发行版时使用此选项。
- -Os 使用了全部-O2的优化选项,但又不缩减代码尺寸的方法 https://www.cnblogs.com/luolizhi/p/5737091.html
- -nostartfiles 链接的使用不使用标准系统库。只有你指定的库才可以传递给链接器。不连接系统标准启动文件,而标准库文件仍然正常使用
- -fno-asynchronous-unwind-tables 用来不生成CFI指令
- -o 输出文件名
- stribe 给文件脱裤子。具体就是从特定文件中剥掉一些符号信息和调试信息。 在strip以后, 文件变小了, 仍然能够执行, 这就就节省了不少空间。