Skip to content

Commit

Permalink
Build multistage dockerfile by stage
Browse files Browse the repository at this point in the history
This commit adds two functions to implement building a multistage
dockerfile to get its images by the stages.

1. get_multistage_image_dockerfiles() at
tern\analyze\docker\dockerfile.py: This function splits a multistage
dockerfile into dockerfiles by its stage for build.

2. build_multistage() at tern\analyze\docker\run.py: This functions
builds a multistage dockerfile to get the images for analyze. So far we
can build the dockerfile and the further jobs like analyze and clean up
are implement by other commits.

Works towards tern-tools#612.

Signed-off-by: WangJL <hazard15020@gmail.com>
  • Loading branch information
ForgetMe17 committed Jul 23, 2020
1 parent 98948d5 commit 2bcb98d
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
39 changes: 39 additions & 0 deletions tern/analyze/docker/dockerfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import re
import logging
import copy
import os

from tern.utils import general
from tern.utils import constants
Expand Down Expand Up @@ -363,3 +364,41 @@ def split_multistage_dockerfile(dfobj):
# dfobj_temp not empty, append to the list
dfobj_list.append(copy.copy(dfobj_temp))
return dfobj_list


def get_multistage_image_dockerfiles(dfobj_multi):
"""Given a multistage dockerfile object, return a list of structures
for building image."""
file_path_list = []
structure = []
idx = 0
for command_dict in dfobj_multi.structure:
if command_dict['instruction'] == 'FROM':
if structure:
file_path = dfobj_multi.filepath + '_%d' % (idx)
# we make a new dir for the dockerfile of each stage.
if not os.path.isdir(file_path):
os.mkdir(file_path)
file_path += '/Dockerfile'
idx += 1
write_dockerfile_by_structure(file_path, structure)
file_path_list.append(file_path)
structure.append(command_dict)
# append last file_path
if structure:
file_path = dfobj_multi.filepath + '_%d' % (idx)
# we make a new dir for the dockerfile of each stage.
if not os.path.isdir(file_path):
os.mkdir(file_path)
file_path += '/Dockerfile'
write_dockerfile_by_structure(file_path, structure)
file_path_list.append(file_path)
return file_path_list


def write_dockerfile_by_structure(file_name, structure):
"""Given a dockerfile name and its structure, write the content into the
dockerfile."""
with open(file_name, 'w') as f:
for st in structure:
f.write(st['content'])
23 changes: 23 additions & 0 deletions tern/analyze/docker/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,26 @@ def execute_dockerfile(args): # noqa C901,R0912
if args.name == 'report':
if not args.keep_wd:
report.clean_working_dir()


def build_multistage(dockerfile_path):
"""Given a multistage dockerfile, first get the dockerfiles for each
stage and then build the dockerfiles.
TO DO:
1.Add image analyze
2. Clean the temp dockerfiles"""
dfobj_multi = dockerfile.get_dockerfile_obj(dockerfile_path)
file_path_list = dockerfile.get_multistage_image_dockerfiles(dfobj_multi)
print(file_path_list)
for dfile in file_path_list:
dfobj = dockerfile.get_dockerfile_obj(dfile)
# expand potential ARG values so base image tag is correct
dockerfile.expand_arg(dfobj)
dockerfile.expand_vars(dfobj)
report.setup(dfobj=dfobj)
# attempt to build the image
logger.debug('Building Docker image...')
# placeholder to check if we can analyze the full image
build, _ =dhelper.is_build()
print(build)
# TO DO: Add image analyze here to analyze each image.

0 comments on commit 2bcb98d

Please sign in to comment.