Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Sep 3, 2022. It is now read-only.

Commit 4e58926

Browse files
authored
Create a GPU docker container for Datalab. (#1367)
* Create a GPU docker container for Datalab. Based off of the nvidia Ubuntu 16.04 container. Also switching the non-GPU container to an Ubuntu 16.04 base image for consistency. * Changes based on review comments. * Make the release scripts build/push the GPU image. * Add GPU to the rollback. Adding it at the end to cover the case where it doesn't exist. * Changes based on review comments. * Add a create-gpu command to the datalab cli tool. * Exit cleanly on rollback if there is no previous GPU image. * Updates based on review comments. * Fix flake8 errors.
1 parent 146a916 commit 4e58926

File tree

13 files changed

+527
-72
lines changed

13 files changed

+527
-72
lines changed

containers/base/Dockerfile

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
FROM debian:jessie
15+
# We use different base images for GPU vs CPU Dockerfiles, so we expect
16+
# that the appropriate image is pulled and tagged locally.
17+
# CPU should use ubuntu:16.04
18+
# and GPU uses nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04
19+
FROM datalab-external-base-image
1620
MAINTAINER Google Cloud DataLab
1721

1822
# Container configuration
@@ -34,7 +38,10 @@ RUN echo "deb-src http://ftp.us.debian.org/debian testing main" >> /etc/apt/sour
3438
# Save GPL source packages
3539
mkdir -p /srcs && \
3640
cd /srcs && \
37-
apt-get source -d wget git python-zmq ca-certificates pkg-config libpng-dev && \
41+
# We have to use allow-unauthenticated since Ubuntu can't verify the keys for the source
42+
# repos. We don't care since we only download these sources for licensing reasons and
43+
# don't actually use them.
44+
apt-get source --allow-unauthenticated -d wget git python-zmq ca-certificates pkg-config libpng-dev && \
3845
wget --progress=dot:mega https://mirrors.kernel.org/gnu/gcc/gcc-4.9.2/gcc-4.9.2.tar.bz2 && \
3946
cd / && \
4047

@@ -168,11 +175,9 @@ RUN echo "deb-src http://ftp.us.debian.org/debian testing main" >> /etc/apt/sour
168175
tools/google-cloud-sdk/bin/gcloud config set component_manager/disable_update_check true && \
169176
touch /tools/google-cloud-sdk/lib/third_party/google.py && \
170177

171-
# locale
172-
DEBIAN_FRONTEND=noninteractive apt-get install -y locales && \
173-
sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
174-
echo 'LANG="en_US.UTF-8"'>/etc/default/locale && \
175-
dpkg-reconfigure --frontend=noninteractive locales && \
178+
# Set our locale to en_US.UTF-8.
179+
apt-get install -y locales && \
180+
locale-gen en_US.UTF-8 && \
176181
update-locale LANG=en_US.UTF-8 && \
177182

178183
# Add some unchanging bits - specifically node modules (that need to be kept in sync
@@ -191,7 +196,7 @@ RUN echo "deb-src http://ftp.us.debian.org/debian testing main" >> /etc/apt/sour
191196
/tools/node/bin/npm install -g forever && \
192197

193198
# Clean up
194-
apt-get purge -y build-essential bzip2 cpp cpp-4.9 python-setuptools pkg-config libfreetype6-dev && \
199+
apt-get purge -y build-essential bzip2 cpp pkg-config libfreetype6-dev && \
195200
apt-get autoremove -y && \
196201
rm -rf /var/lib/apt/lists/* && \
197202
rm -rf /var/lib/dpkg/info/* && \

containers/base/Dockerfile.gpu

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2017 Google Inc. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
FROM datalab-core-gpu
16+
MAINTAINER Google Cloud DataLab
17+
18+
# Download and Install GPU specific packages
19+
RUN pip install -U --upgrade-strategy only-if-needed --no-cache-dir tensorflow-gpu==1.0.1 && \
20+
pip3 install -U --upgrade-strategy only-if-needed --no-cache-dir tensorflow-gpu==1.0.1
21+
22+

containers/base/build.gpu.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/bash -e
2+
# Copyright 2015 Google Inc. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Builds the Google Cloud DataLab base docker image. Usage:
17+
# build.sh [path_of_pydatalab_dir]
18+
# If [path_of_pydatalab_dir] is provided, it will copy the content of that dir into image.
19+
# Otherwise, it will get the pydatalab by "git clone" from pydatalab repo.
20+
21+
# Build the docker image
22+
if [ -n "$1" ]; then
23+
src_pydatalab=$(realpath "$1")
24+
25+
cd $(dirname $0)
26+
rsync -avp "$src_pydatalab"/ pydatalab
27+
else
28+
# Create empty dir to make docker build happy.
29+
cd $(dirname $0)
30+
mkdir -p pydatalab
31+
fi
32+
33+
trap 'rm -rf pydatalab' exit
34+
35+
docker pull nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04
36+
# Docker tag flags changed in an incompatible way between versions.
37+
# The Datalab Jenkins build still uses the old one, so try it both ways.
38+
if ! $(docker tag -f nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04 datalab-external-base-image); then
39+
docker tag nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04 datalab-external-base-image
40+
fi
41+
docker build ${DOCKER_BUILD_ARGS} -t datalab-core-gpu .
42+
docker build ${DOCKER_BUILD_ARGS} -f Dockerfile.gpu -t datalab-base-gpu .

containers/base/build.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,11 @@ else
3131
fi
3232

3333
trap 'rm -rf pydatalab' exit
34+
35+
docker pull ubuntu:16.04
36+
# Docker tag flags changed in an incompatible way between versions.
37+
# The Datalab Jenkins build still uses the old one, so try it both ways.
38+
if ! $(docker tag -f ubuntu:16.04 datalab-external-base-image); then
39+
docker tag ubuntu:16.04 datalab-external-base-image
40+
fi
3441
docker build ${DOCKER_BUILD_ARGS} -t datalab-base .

containers/datalab/Dockerfile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
FROM datalab-base
15+
FROM _base_image_
1616
MAINTAINER Google Cloud DataLab
1717

1818
# Add build artifacts

containers/datalab/build.gpu.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/bash -e
2+
# Copyright 2015 Google Inc. All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Builds the Google Cloud DataLab docker image. Usage:
17+
# build.sh [path_of_pydatalab_dir]
18+
# If [path_of_pydatalab_dir] is provided, it will copy the content of that dir into image.
19+
# Otherwise, it will get the pydatalab by "git clone" from pydatalab repo.
20+
21+
# Create a versioned Dockerfile based on current date and git commit hash
22+
VERSION=`date +%Y%m%d`
23+
VERSION_SUBSTITUTION="s/_version_/0.5.$VERSION/"
24+
25+
COMMIT=`git log --pretty=format:'%H' -n 1`
26+
COMMIT_SUBSTITUTION="s/_commit_/$COMMIT/"
27+
28+
BASE_IMAGE_SUBSTITUTION="s/_base_image_/datalab-base-gpu/"
29+
30+
if [ -z "$1" ]; then
31+
pydatalabPath=''
32+
else
33+
pydatalabPath=$(realpath "$1")
34+
fi
35+
36+
cd $(dirname $0)
37+
38+
cat Dockerfile.in | sed $VERSION_SUBSTITUTION | sed $COMMIT_SUBSTITUTION | sed $BASE_IMAGE_SUBSTITUTION > Dockerfile
39+
40+
# Set up our required environment
41+
source ../../tools/initenv.sh
42+
43+
# Build the datalab frontend
44+
../../sources/web/build.sh
45+
46+
# Copy build outputs as a dependency of the Dockerfile
47+
rsync -avp ../../build/ build
48+
49+
# Copy the license file into the container
50+
cp ../../third_party/license.txt content/license.txt
51+
52+
# Build the base docker image
53+
../base/build.gpu.sh "$pydatalabPath"
54+
55+
# Build the docker image
56+
docker build ${DOCKER_BUILD_ARGS} -t datalab-gpu .
57+
58+
# Finally cleanup
59+
rm -rf build
60+
rm content/license.txt
61+
rm Dockerfile

containers/datalab/build.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ source $HERE/../../tools/release/version.sh
2626
VERSION_SUBSTITUTION="s/_version_/$DATALAB_VERSION/"
2727
COMMIT_SUBSTITUTION="s/_commit_/$DATALAB_COMMIT/"
2828

29+
BASE_IMAGE_SUBSTITUTION="s/_base_image_/datalab-base/"
30+
2931
if [ -z "$1" ]; then
3032
pydatalabPath=''
3133
else
@@ -34,7 +36,7 @@ fi
3436

3537
cd $(dirname $0)
3638

37-
cat Dockerfile.in | sed $VERSION_SUBSTITUTION | sed $COMMIT_SUBSTITUTION > Dockerfile
39+
cat Dockerfile.in | sed $VERSION_SUBSTITUTION | sed $COMMIT_SUBSTITUTION | sed $BASE_IMAGE_SUBSTITUTION > Dockerfile
3840

3941
# Set up our required environment
4042
source ../../tools/initenv.sh

tools/cli/commands/create.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545
_DATALAB_NOTEBOOKS_REPOSITORY = 'datalab-notebooks'
4646

47-
_DATALAB_STARTUP_SCRIPT = """#!/bin/bash
47+
_DATALAB_BASE_STARTUP_SCRIPT = """#!/bin/bash
4848
4949
PERSISTENT_DISK_DEV="/dev/disk/by-id/google-datalab-pd"
5050
MOUNT_DIR="/mnt/disks/datalab-pd"
@@ -148,6 +148,9 @@
148148
find "${{tmpdir}}/" -mindepth 1 -delete
149149
}}
150150
151+
"""
152+
153+
_DATALAB_STARTUP_SCRIPT = _DATALAB_BASE_STARTUP_SCRIPT + """
151154
mount_and_prepare_disk
152155
configure_swap
153156
cleanup_tmp
@@ -524,38 +527,56 @@ def ensure_repo_exists(args, gcloud_repos, repo_name):
524527
raise RepositoryException(repo_name)
525528

526529

527-
def run(args, gcloud_compute, gcloud_repos,
528-
email='', in_cloud_shell=False, **kwargs):
529-
"""Implementation of the `datalab create` subcommand.
530+
def prepare(args, gcloud_compute, gcloud_repos):
531+
"""Run preparation steps for VM creation.
530532
531533
Args:
532534
args: The Namespace instance returned by argparse
533535
gcloud_compute: Function that can be used to invoke `gcloud compute`
534536
gcloud_repos: Function that can be used to invoke
535537
`gcloud source repos`
536-
email: The user's email address
537-
in_cloud_shell: Whether or not the command is being run in the
538-
Google Cloud Shell
538+
Returns:
539+
The disk config
539540
Raises:
540541
subprocess.CalledProcessError: If a nested `gcloud` calls fails
541542
"""
542543
ensure_network_exists(args, gcloud_compute)
543544
ensure_firewall_rule_exists(args, gcloud_compute)
544545

545-
instance = args.instance
546-
disk_name = args.disk_name or '{0}-pd'.format(instance)
546+
disk_name = args.disk_name or '{0}-pd'.format(args.instance)
547547
ensure_disk_exists(args, gcloud_compute, disk_name)
548+
disk_cfg = (
549+
'auto-delete=no,boot=no,device-name=datalab-pd,mode=rw,name=' +
550+
disk_name)
548551

549552
if not args.no_create_repository:
550553
ensure_repo_exists(args, gcloud_repos, _DATALAB_NOTEBOOKS_REPOSITORY)
551554

552-
print('Creating the instance {0}'.format(instance))
555+
return disk_cfg
556+
557+
558+
def run(args, gcloud_compute, gcloud_repos,
559+
email='', in_cloud_shell=False, **kwargs):
560+
"""Implementation of the `datalab create` subcommand.
561+
562+
Args:
563+
args: The Namespace instance returned by argparse
564+
gcloud_compute: Function that can be used to invoke `gcloud compute`
565+
gcloud_repos: Function that can be used to invoke
566+
`gcloud source repos`
567+
email: The user's email address
568+
in_cloud_shell: Whether or not the command is being run in the
569+
Google Cloud Shell
570+
Raises:
571+
subprocess.CalledProcessError: If a nested `gcloud` calls fails
572+
"""
573+
disk_cfg = prepare(args, gcloud_compute, gcloud_repos)
574+
575+
print('Creating the instance {0}'.format(args.instance))
553576
cmd = ['instances', 'create']
554577
if args.zone:
555578
cmd.extend(['--zone', args.zone])
556-
disk_cfg = (
557-
'auto-delete=no,boot=no,device-name=datalab-pd,mode=rw,name=' +
558-
disk_name)
579+
559580
enable_backups = "false" if args.no_backups else "true"
560581
console_log_level = args.log_level or "warn"
561582
user_email = args.for_user or email
@@ -602,7 +623,7 @@ def run(args, gcloud_compute, gcloud_repos,
602623
'--disk', disk_cfg,
603624
'--service-account', service_account,
604625
'--scopes', 'cloud-platform',
605-
instance])
626+
args.instance])
606627
gcloud_compute(args, cmd)
607628
finally:
608629
os.remove(startup_script_file.name)

0 commit comments

Comments
 (0)