dockerコマンドのbuild
9493 ワード
dockerコマンドのbuild
1 man docker-build
1 man docker-build
NAME docker-build - Build an image from a Dockerfile source at PATH SYNOPSIS docker build [--no-cache[=false]] [-q|--quiet[=false]] [--rm] [-t|--tag=TAG] PATH | URL | - DESCRIPTION This will read the Dockerfile from the directory specified in PATH. It also sends any other files and directories found in the current directory to the Docker daemon. The contents of this directory would be used by ADD commands found within the Dockerfile. Warning, this will send a lot of data to the Docker daemon depending on the contents of the current directory. The build is run by the Docker daemon, not by the CLI, so the whole context must be transferred to the daemon. The Docker CLI reports "Sending build context to Docker daemon"when the context is sent to the daemon. When a single Dockerfile is given as the URL, then no context is set. When a Git repository is set as the URL, the repository is used as context. OPTIONS -q, --quiet=true|false When set to true, suppress verbose build output. Default is false. --rm=true|false When true, remove intermediate containers that are created during the build process. The default is true. -t, --tag=tag The name to be applied to the resulting image on successful completion of the build. tag in this context means the entire image name including the optional TAG after the ':'. --no-cache=true|false When set to true, do not use a cache when building the image. The default is false.
2プロセス
実行コマンド:docker build--rm-tag tt.
2.1クライアント側
CmdBuild(api/client/command.go) -----> postBuild(api/server/server.go) ------> CmdBuild(builder/job.go)
ClientのCmdBuildメソッドは主にbuildパラメータとbuild環境が要求を満たしているかどうかを確認した後、解析したパラメータをPOSTでhttpserverに要求し、この部分は分析しなくなった.
ここでtag=tt,rm:1,その他のパラメータはデフォルトまたは空です
2.2 serverエンド
クライアントからのリクエストを解析し、jobが実行する環境変数を構成します.docker buildコマンドラインに対応するパラメータが指定されていない場合は、システムのデフォルト構成の環境を使用します.デフォルトのパラメータは次のとおりです.
--force-rm=false Always remove intermediate containers, even after unsuccessful builds --no-cache=false Do not use cache when building the image -q, --quiet=false Suppress the verbose output generated by the containers --rm=true Remove intermediate containers after a successful build -t, --tag="" Repository name (and optionally a tag) to be applied to the resulting image in case of success var (
authEncoded = r.Header.Get("X-Registry-Auth")
authConfig = ®istry.AuthConfig{}
configFileEncoded = r.Header.Get("X-Registry-Config")
configFile = ®istry.ConfigFile{}
job = eng.Job("build")
)
if r.FormValue("forcerm") == "1" && version.GreaterThanOrEqualTo("1.12") {
job.Setenv("rm", "1")
} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
job.Setenv("rm", "1")
} else {
job.Setenv("rm", r.FormValue("rm"))
}
job.Stdin.Add(r.Body)
job.Setenv("remote", r.FormValue("remote"))
job.Setenv("t", r.FormValue("t"))
job.Setenv("q", r.FormValue("q"))
job.Setenv("nocache", r.FormValue("nocache"))
job.Setenv("forcerm", r.FormValue("forcerm"))
job.SetenvJson("authConfig", authConfig)
job.SetenvJson("configFile", configFile)
運転jobif err := job.Run(); err != nil {
if !job.Stdout.Used() {
return err
}
sf := utils.NewStreamFormatter(version.GreaterThanOrEqualTo("1.8"))
w.Write(sf.FormatError(err))
}
2.3 job端子
build jobインストール、build動作を処理するjob関数体.func (b *BuilderJob) Install() {
b.Engine.Register("build", b.CmdBuild)
}
job環境変数を解析します.ここでrm=1,repoName=tt,tag=latestvar (
remoteURL = job.Getenv("remote")
repoName = job.Getenv("t")
suppressOutput = job.GetenvBool("q")
noCache = job.GetenvBool("nocache")
rm = job.GetenvBool("rm")
forceRm = job.GetenvBool("forcerm")
authConfig = ®istry.AuthConfig{}
configFile = ®istry.ConfigFile{}
tag string
context io.ReadCloser
)
job.GetenvJson("authConfig", authConfig)
job.GetenvJson("configFile", configFile)
repoName, tag = parsers.ParseRepositoryTag(repoName)
本例では、次のコードセグメントを用いてdockerfileを処理し、dockerfileの内容をcontextファイルに読み出す.dockerfileを取得するには、ローカルから取得するモードとgitから取得するモード、URLから取得するモードの3つがあります.if remoteURL == "" {
context = ioutil.NopCloser(job.Stdin)
} else if urlutil.IsGitURL(remoteURL) {
...
}
} else if utils.IsURL(remoteURL) {
...
}
buildを実行するタスク構造体を新規に作成し、関数の前に収集した情報をこの構造体に埋め込み、今回のbuildの環境とします.builder := &Builder{
Daemon: b.Daemon,
Engine: b.Engine,
OutStream: &utils.StdoutFormater{
Writer: job.Stdout,
StreamFormatter: sf,
},
ErrStream: &utils.StderrFormater{
Writer: job.Stdout,
StreamFormatter: sf,
},
Verbose: !suppressOutput,
UtilizeCache: !noCache,
Remove: rm,
ForceRemove: forceRm,
OutOld: job.Stdout,
StreamFormatter: sf,
AuthConfig: authConfig,
AuthConfigFile: configFile,
}
builderタスクの実行id, err := builder.Run(context)
if err != nil {
return job.Error(err)
}
buildタスクが完了したら、repoName、tag、idなどの情報を保存します.if repoName != "" {
b.Daemon.Repositories().Set(repoName, tag, id, false)
}
builderのRunはbuilder/evaluatorにある.goではbuilderの1つの方法です.
この方法はRunパラメータcontextの内容を読み取ることによってファイルに読み込まれ,このファイルの内容を解析するが,このファイルの内容はDockerfileの内容である.
Dockerfileで使用するコマンドはファイルdispatchers.goのメソッドはevaluatorによってルーティングされる.goファイルが責任を負います.これはDockerfileファイルのコマンドです.
対応する処理方法.func init() {
evaluateTable = map[string]func(*Builder, []string, map[string]bool) error{
"env": env,
"maintainer": maintainer,
"add": add,
"copy": dispatchCopy, // copy() is a go builtin
"from": from,
"onbuild": onbuild,
"workdir": workdir,
"docker-version": nullDispatch, // we don't care about docker-version
"run": run,
"cmd": cmd,
"entrypoint": entrypoint,
"expose": expose,
"volume": volume,
"user": user,
"insert": insert,
}
}
runメソッドの分析
コンテンツの読み込みif err := b.readContext(context); err != nil {
return "", err
}
生成されたDockerfileファイルを対応するパスに挿入filename := path.Join(b.contextPath, "Dockerfile")
ファイルの内容を読み込むf, err := os.Open(filename)
if err != nil {
return "", err
}
Dockerfileファイルの内容を解析し、これらのDockerfileコマンドを実行する準備をします.ast, err := parser.Parse(f)
if err != nil {
return "", err
}
b.dockerfile = ast
Dockerfileコマンドを実行し、b.dispatherによってコマンド配布を行う.コマンドラインに--force-rm=trueパラメータがある場合は、コマンド実行に失敗したContainerを削除します.dockerfileの各行はdockerfileコマンドであり、各コマンドの実行はContainerを新規作成し、すべてのdockerfileコマンドが実行されるまで、コマンドの実行結果をミラーのレイヤに書き込みます.このプロセスで生成されたContainerは、パラメータを実行することによって
--rm=true、build中に生成された一時Containerを削除します.またdispatchにはdockerfileが使用できないコマンドをフィルタリングする機能もあります.b.Config = &runconfig.Config{Entrypoint: []string{}, Cmd: []string{"/bin/sh", "-c"}}
b.TmpContainers = map[string]struct{}{}
for i, n := range b.dockerfile.Children {
if err := b.dispatch(i, n); err != nil {
if b.ForceRemove {
b.clearTmp()
}
return "", err
}
fmt.Fprintf(b.OutStream, " ---> %s
", utils.TruncateID(b.image))
if b.Remove {
b.clearTmp()
}
}
buildによって生成されたミラーidを返すfmt.Fprintf(b.OutStream, "Successfully built %s
", utils.TruncateID(b.image))
return b.image, nil
Dockerfileの各コマンドにはエントリがあり、dispatchメソッドで配布され、Dockerfileコマンドに対応するhandlerはdispatchersにある.goでは、
しかし、最後にcommitメソッドに渡され、commitメソッドはinternalsにある.goでは、各コマンドの実行はContainerを新規作成することで完了します.
最後に、各コマンドの実行結果をlayerにコミットします.if id == "" {
cmd := b.Config.Cmd
b.Config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment}
defer func(cmd []string) { b.Config.Cmd = cmd }(cmd)
hit, err := b.probeCache()
if err != nil {
return err
}
if hit {
return nil
}
container, err := b.create()
if err != nil {
return err
}
id = container.ID
if err := container.Mount(); err != nil {
return err
}
defer container.Unmount()
}
// Commit the container
image, err := b.Daemon.Commit(container, "", "", "", b.maintainer, true, &autoConfig)
if err != nil {
return err
}
実行コマンド:docker build--rm-tag tt.
2.1クライアント側
CmdBuild(api/client/command.go) -----> postBuild(api/server/server.go) ------> CmdBuild(builder/job.go)
ClientのCmdBuildメソッドは主にbuildパラメータとbuild環境が要求を満たしているかどうかを確認した後、解析したパラメータをPOSTでhttpserverに要求し、この部分は分析しなくなった.
ここでtag=tt,rm:1,その他のパラメータはデフォルトまたは空です
2.2 serverエンド
クライアントからのリクエストを解析し、jobが実行する環境変数を構成します.docker buildコマンドラインに対応するパラメータが指定されていない場合は、システムのデフォルト構成の環境を使用します.デフォルトのパラメータは次のとおりです.
--force-rm=false Always remove intermediate containers, even after unsuccessful builds --no-cache=false Do not use cache when building the image -q, --quiet=false Suppress the verbose output generated by the containers --rm=true Remove intermediate containers after a successful build -t, --tag="" Repository name (and optionally a tag) to be applied to the resulting image in case of success
var (
authEncoded = r.Header.Get("X-Registry-Auth")
authConfig = ®istry.AuthConfig{}
configFileEncoded = r.Header.Get("X-Registry-Config")
configFile = ®istry.ConfigFile{}
job = eng.Job("build")
)
if r.FormValue("forcerm") == "1" && version.GreaterThanOrEqualTo("1.12") {
job.Setenv("rm", "1")
} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
job.Setenv("rm", "1")
} else {
job.Setenv("rm", r.FormValue("rm"))
}
job.Stdin.Add(r.Body)
job.Setenv("remote", r.FormValue("remote"))
job.Setenv("t", r.FormValue("t"))
job.Setenv("q", r.FormValue("q"))
job.Setenv("nocache", r.FormValue("nocache"))
job.Setenv("forcerm", r.FormValue("forcerm"))
job.SetenvJson("authConfig", authConfig)
job.SetenvJson("configFile", configFile)
運転jobif err := job.Run(); err != nil {
if !job.Stdout.Used() {
return err
}
sf := utils.NewStreamFormatter(version.GreaterThanOrEqualTo("1.8"))
w.Write(sf.FormatError(err))
}
2.3 job端子
build jobインストール、build動作を処理するjob関数体.
func (b *BuilderJob) Install() {
b.Engine.Register("build", b.CmdBuild)
}
job環境変数を解析します.ここでrm=1,repoName=tt,tag=latestvar (
remoteURL = job.Getenv("remote")
repoName = job.Getenv("t")
suppressOutput = job.GetenvBool("q")
noCache = job.GetenvBool("nocache")
rm = job.GetenvBool("rm")
forceRm = job.GetenvBool("forcerm")
authConfig = ®istry.AuthConfig{}
configFile = ®istry.ConfigFile{}
tag string
context io.ReadCloser
)
job.GetenvJson("authConfig", authConfig)
job.GetenvJson("configFile", configFile)
repoName, tag = parsers.ParseRepositoryTag(repoName)
本例では、次のコードセグメントを用いてdockerfileを処理し、dockerfileの内容をcontextファイルに読み出す.dockerfileを取得するには、ローカルから取得するモードとgitから取得するモード、URLから取得するモードの3つがあります.if remoteURL == "" {
context = ioutil.NopCloser(job.Stdin)
} else if urlutil.IsGitURL(remoteURL) {
...
}
} else if utils.IsURL(remoteURL) {
...
}
buildを実行するタスク構造体を新規に作成し、関数の前に収集した情報をこの構造体に埋め込み、今回のbuildの環境とします.
builder := &Builder{
Daemon: b.Daemon,
Engine: b.Engine,
OutStream: &utils.StdoutFormater{
Writer: job.Stdout,
StreamFormatter: sf,
},
ErrStream: &utils.StderrFormater{
Writer: job.Stdout,
StreamFormatter: sf,
},
Verbose: !suppressOutput,
UtilizeCache: !noCache,
Remove: rm,
ForceRemove: forceRm,
OutOld: job.Stdout,
StreamFormatter: sf,
AuthConfig: authConfig,
AuthConfigFile: configFile,
}
builderタスクの実行id, err := builder.Run(context)
if err != nil {
return job.Error(err)
}
buildタスクが完了したら、repoName、tag、idなどの情報を保存します.
if repoName != "" {
b.Daemon.Repositories().Set(repoName, tag, id, false)
}
builderのRunはbuilder/evaluatorにある.goではbuilderの1つの方法です.
この方法はRunパラメータcontextの内容を読み取ることによってファイルに読み込まれ,このファイルの内容を解析するが,このファイルの内容はDockerfileの内容である.
Dockerfileで使用するコマンドはファイルdispatchers.goのメソッドはevaluatorによってルーティングされる.goファイルが責任を負います.これはDockerfileファイルのコマンドです.
対応する処理方法.
func init() {
evaluateTable = map[string]func(*Builder, []string, map[string]bool) error{
"env": env,
"maintainer": maintainer,
"add": add,
"copy": dispatchCopy, // copy() is a go builtin
"from": from,
"onbuild": onbuild,
"workdir": workdir,
"docker-version": nullDispatch, // we don't care about docker-version
"run": run,
"cmd": cmd,
"entrypoint": entrypoint,
"expose": expose,
"volume": volume,
"user": user,
"insert": insert,
}
}
runメソッドの分析コンテンツの読み込み
if err := b.readContext(context); err != nil {
return "", err
}
生成されたDockerfileファイルを対応するパスに挿入
filename := path.Join(b.contextPath, "Dockerfile")
ファイルの内容を読み込む
f, err := os.Open(filename)
if err != nil {
return "", err
}
Dockerfileファイルの内容を解析し、これらのDockerfileコマンドを実行する準備をします.
ast, err := parser.Parse(f)
if err != nil {
return "", err
}
b.dockerfile = ast
Dockerfileコマンドを実行し、b.dispatherによってコマンド配布を行う.コマンドラインに--force-rm=trueパラメータがある場合は、コマンド実行に失敗したContainerを削除します.dockerfileの各行はdockerfileコマンドであり、各コマンドの実行はContainerを新規作成し、すべてのdockerfileコマンドが実行されるまで、コマンドの実行結果をミラーのレイヤに書き込みます.このプロセスで生成されたContainerは、パラメータを実行することによって--rm=true、build中に生成された一時Containerを削除します.またdispatchにはdockerfileが使用できないコマンドをフィルタリングする機能もあります.
b.Config = &runconfig.Config{Entrypoint: []string{}, Cmd: []string{"/bin/sh", "-c"}}
b.TmpContainers = map[string]struct{}{}
for i, n := range b.dockerfile.Children {
if err := b.dispatch(i, n); err != nil {
if b.ForceRemove {
b.clearTmp()
}
return "", err
}
fmt.Fprintf(b.OutStream, " ---> %s
", utils.TruncateID(b.image))
if b.Remove {
b.clearTmp()
}
}
buildによって生成されたミラーidを返すfmt.Fprintf(b.OutStream, "Successfully built %s
", utils.TruncateID(b.image))
return b.image, nil
Dockerfileの各コマンドにはエントリがあり、dispatchメソッドで配布され、Dockerfileコマンドに対応するhandlerはdispatchersにある.goでは、
しかし、最後にcommitメソッドに渡され、commitメソッドはinternalsにある.goでは、各コマンドの実行はContainerを新規作成することで完了します.
最後に、各コマンドの実行結果をlayerにコミットします.
if id == "" {
cmd := b.Config.Cmd
b.Config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment}
defer func(cmd []string) { b.Config.Cmd = cmd }(cmd)
hit, err := b.probeCache()
if err != nil {
return err
}
if hit {
return nil
}
container, err := b.create()
if err != nil {
return err
}
id = container.ID
if err := container.Mount(); err != nil {
return err
}
defer container.Unmount()
}
// Commit the container
image, err := b.Daemon.Commit(container, "", "", "", b.maintainer, true, &autoConfig)
if err != nil {
return err
}