Skip to content

Commit b6d8e89

Browse files
authored
Merge pull request #170 from sympy/dockerize
Dockerize the project for easy development and testing
2 parents a46c8a7 + 6d304d9 commit b6d8e89

File tree

9 files changed

+140
-143
lines changed

9 files changed

+140
-143
lines changed

.travis.yml

+9-28
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,23 @@ language: python
22
python:
33
- '2.7'
44

5-
cache:
6-
directories:
7-
- "$HOME/google-cloud-sdk/"
5+
services:
6+
- docker
87

9-
virtualenv:
10-
system_site_packages: true
11-
12-
addons:
13-
chrome: stable
14-
15-
# Stub: do nothing
8+
# Do nothing
169
before_install:
1710
- ls
1811
install:
19-
- pip install -r requirements/requirements.txt -t lib/
20-
- pip install -r requirements/local_requirements.txt
12+
- ls
2113

2214
before_script:
23-
- cd ..
24-
- gcloud version || true
25-
- if [ ! -d "$HOME/google-cloud-sdk/bin" ]; then rm -rf "$HOME/google-cloud-sdk"; curl https://sdk.cloud.google.com | bash > /dev/null; fi
26-
- source /home/travis/google-cloud-sdk/path.bash.inc
27-
- gcloud version
28-
- gcloud components install cloud-datastore-emulator --quiet
29-
- gcloud beta emulators datastore start &
30-
- wget https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.90.zip -nv
31-
- unzip -q google_appengine_1.9.90.zip
32-
- export SDK_LOCATION="$(pwd)/google_appengine"
33-
- wget https://chromedriver.storage.googleapis.com/81.0.4044.69/chromedriver_linux64.zip
34-
- unzip -q chromedriver_linux64.zip
35-
- cp chromedriver $HOME/bin/
36-
- cd $TRAVIS_BUILD_DIR
37-
- python $SDK_LOCATION/dev_appserver.py --skip_sdk_update_check 1 . --env_var DATASTORE_EMULATOR_HOST=localhost:8081 --env_var DATASTORE_USE_PROJECT_ID_AS_APP_ID=true &
15+
- docker-compose up -d
3816
script:
39-
- pytest tests -v
17+
- sleep 2 # Wait for api to be up
18+
- docker-compose exec app pytest tests/ -v
4019

4120
before_deploy:
21+
- docker cp app:/usr/src/app/lib lib
4222
- openssl aes-256-cbc -K $encrypted_2fd045226a67_key -iv $encrypted_2fd045226a67_iv
4323
-in client-secret.json.enc -out ../client-secret.json -d
4424
- version=$(if [ ! -z "$TRAVIS_TAG" ]; then echo $(cut -d'-' -f2 <<<"$TRAVIS_TAG");
@@ -62,6 +42,7 @@ after_deploy:
6242
- status_code=$(curl --write-out %{http_code} --silent --output /dev/null https://$version-dot-sympy-live-hrd.appspot.com/status)
6343
- echo "App status code => $status_code"
6444
- if [ "$status_code" != "200" ]; then travis_terminate; fi
45+
- docker-compose down
6546

6647
env:
6748
global:

README.rst

+35-114
Original file line numberDiff line numberDiff line change
@@ -20,87 +20,33 @@ evaluation request is a subject to this limit. There are also other limits
2020
related to memory consumption, output size, etc. (see Google App Engine
2121
documentation for details).
2222

23-
Installation
24-
------------
25-
26-
Download 1.9.xx version of the original Google App Engine SDK for Python from
27-
https://cloud.google.com/appengine/docs/python/download/ - it may be neccessary
28-
to click ``Or, you can download the original App Engine SDK for Python.`` link
29-
first to expand proper download section. Than move in the command line to the
30-
location where you downloaded SDK and unpack the downloaded package.
31-
32-
$ unzip google_appengine_1.9.xx.zip
33-
34-
On the Mac, it is a disk image with an application, which you should
35-
drag to your Applications folder. Open the program and install the
36-
symlinks (it should ask you the first time you open the application, but
37-
if it doesn't, choose "Make Symlinks..." from the
38-
GoogleAppEngineLauncher menu). Note that you will have to do this again
39-
each time you update the AppEngine program.
40-
41-
Then clone sympy-live repository::
42-
43-
$ git clone git://github.com/sympy/sympy-live.git
44-
$ cd sympy-live
45-
46-
We use submodules to include external libraries in sympy-live::
47-
48-
$ git submodule init
49-
$ git submodule update
50-
51-
This is sufficient to clone appropriate repositories in correct versions
52-
into sympy-live (see git documentation on submodules for information).
53-
54-
You will need to install Datastore Emulator as well, which comes from gcloud's SDK,
55-
install the Google Cloud SDK for your OS from here: https://cloud.google.com/sdk/install
56-
Then run the following commands to install and run the datastore emulator in the background::
57-
58-
$ gcloud components install cloud-datastore-emulator --quiet
59-
$ gcloud beta emulators datastore start &
60-
61-
Install Dependencies
62-
--------------------
63-
64-
The project depends on some third-party libraries that are not on the list
65-
of built-in libraries (in app.yaml) bundled with the runtime, to install them
66-
run the following command.::
67-
68-
$ pip install -r requirements/requirements.txt -t lib/
69-
70-
Some libraries although available on app engine runtime, but needs to be
71-
installed locally for development.
72-
73-
Ref: https://cloud.google.com/appengine/docs/standard/python/tools/using-libraries-python-27#local_development ::
74-
75-
$ pip install -r requirements/local_requirements.txt
76-
77-
Development server
23+
Development Server
7824
------------------
7925

80-
Now you are ready to run development web server::
26+
To setup the development environment and run the app locally, you
27+
need ``docker`` and ``docker-compose``:
8128

82-
$ ../google_appengine/dev_appserver.py .
29+
* https://docs.docker.com/get-docker/
30+
* https://docs.docker.com/compose/install/
8331

84-
On the Mac, just run::
85-
86-
$ dev_appserver .
32+
Now you are ready to run development web server::
8733

88-
(make sure you installed the symlinks as described above).
34+
$ docker-compose up
8935

90-
I couldn't figure out how to make it work in the GUI (it won't find the
91-
sympy git submodule). If you figure out how to do it, please update
92-
this file and send a patch describing how to do it.
36+
This will build and run the image for app and datastore emulator.
9337

94-
This is a local server that runs on port 8080 (use ``--port`` option to
95-
change this). Open a web browser and go to http://localhost:8080. You
96-
should see GUI of SymPy Online Shell.
38+
This will spin up a local server that runs on port ``8080``.
39+
Open a web browser and go to http://localhost:8080.
40+
You should see GUI of SymPy Online Shell.
9741

98-
Deploying to GAE
99-
----------------
42+
Deploying to Google App Engine
43+
------------------------------
10044

10145
Travis-CI is used to deploy automatically to the official server
102-
via Github Releases. Go to https://github.com/sympy/sympy-live/releases
103-
and click on create a release and name the release as `version-NN`
46+
via Github Releases.
47+
48+
* Go to https://github.com/sympy/sympy-live/releases
49+
* Click on create a release and name the release as `version-NN`
10450
where `NN` is the release version. After this travis will automatically
10551
release version `NN`.
10652

@@ -118,6 +64,11 @@ the google cloud console for the project::
11864

11965
$ gcloud init
12066

67+
You need to to create ``lib`` (libraries) before deploying, make sure the development
68+
server is up and running via ``docker-compose``, as mentioned above and create
69+
libraries folder to package with the following command::
70+
71+
$ docker cp app:/usr/src/app/lib lib
12172

12273
Assuming that sympy-live works properly (also across different mainstream web
12374
browsers), you can upload your changes to Google App Engine, replacing the
@@ -160,14 +111,22 @@ Testing on the App Engine
160111
-------------------------
161112

162113
It's usually a good idea to test big changes on the App Engine itself before
163-
deploying, as ``dev_appserver.py`` can only simulate the App Engine. There is
164-
a semi-official testing server at sympy-live-tests.appspot.com. If you want
114+
deploying, as ``dev_appserver.py`` can only simulate the App Engine.
115+
116+
There is a semi-official testing server at sympy-live-tests.appspot.com. If you want
165117
write access to it, just ask Aaron Meurer. The convention there is to push
166118
to the version corresponding to the pull request (so if you have a branch that
167119
is pull request #55, you would push to version 55, and access it by
168120
55-dot-sympy-live-tests.appspot.com). Alternately, you can set up your own
169121
testing server (it's free, though it requires a cell phone to set up).
170122

123+
You need to to create ``lib`` (libraries) before deploying, make sure the development
124+
server is up and running via ``docker-compose``, as mentioned above and create
125+
libraries folder to package with the following command::
126+
127+
$ docker cp app:/usr/src/app/lib lib
128+
129+
171130
Either way, to test, you will need to edit the Project ID in the deploy command
172131
mentioned above with your Project ID and the version you want to deploy to::
173132

@@ -194,51 +153,13 @@ includes Chrome, Firefox, Safari and Internet Explorer. Be extra cautious
194153
about trailing commas in JavaScript object and arrays. IE doesn't allow
195154
them, so you have to remove them, if any were introduced.
196155

197-
GAE development server allows to use any Python interpreter, but Google
198-
App Engine uses Python 2.5, so if the default Python isn't 2.5, then make
199-
sure to test your changes to the server part, if it runs properly on 2.5.
200-
Also don't use any modules that aren't supported by GAE.
201-
202156
Running Tests
203157
-------------
204158

205-
To run the tests you need to have ``pytest`` and ``selenium`` installed. These are
206-
already present in the ``local_requirements.txt``. If you you have installed
207-
them you may skip this step. Otherwise to install testing requirements::
208-
209-
$ pip install selenium pytest
210-
211-
You would also need latest version of one of the supported browsers:
212-
213-
* Chrome: https://www.google.com/chrome/
214-
* Firefox: https://www.mozilla.org/firefox/new/
215-
216-
You need to download the driver for your browser as well:
217-
218-
For chrome, get the driver for your system from here:
219-
https://chromedriver.chromium.org/downloads
220-
221-
Here is an example for Linux::
222-
223-
$ wget https://chromedriver.storage.googleapis.com/81.0.4044.69/chromedriver_linux64.zip
224-
$ unzip -q chromedriver_linux64.zip
225-
226-
For Firefox, get the driver for your system from here:
227-
https://github.com/mozilla/geckodriver/releases
228-
229-
After extracting the browser driver from the zip or tar file, for Unix based systems,
230-
copy the driver to following directory::
231-
232-
$ mv /path/to/ChromeDriver /usr/local/bin
233-
$ mv /path/to/geckodriver /usr/local/bin
234-
235-
For other systems like Windows, you need to put it in PATH.
236-
237-
Now run the application in the background, (See ``dev_appserver`` instructions above to start the app).
238-
239-
Run selenium tests via the following command::
159+
To run tests you need to spinup the container as mentioned above
160+
via ``docker-compose`` and run the following command::
240161

241-
$ pytest tests -v
162+
$ docker-compose exec app pytest tests/ -v
242163

243164
Pulling changes
244165
---------------

bin/update_status_on_pr.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def get_branch_commit_sha(branch_name):
2424
if response.status_code == 200:
2525
response_json = response.json()
2626
else:
27-
raise ValueError('Invalid response from github API')
27+
raise ValueError('Invalid response from github API: %s', response.content)
2828
return response_json[0]['object']['sha']
2929

3030

docker-compose.yml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
version: '3'
2+
3+
services:
4+
app:
5+
build:
6+
context: .
7+
dockerfile: ./docker/app/Dockerfile
8+
image: app
9+
container_name: app
10+
depends_on:
11+
- datastore
12+
volumes:
13+
- ./app/:/usr/src/app/app/
14+
ports:
15+
- "8080:8080"
16+
- "8082:8082"
17+
- "8083:8083"
18+
command: /run.sh
19+
20+
datastore:
21+
build:
22+
context: .
23+
dockerfile: ./docker/datastore/Dockerfile
24+
image: datastore
25+
container_name: datastore
26+
ports:
27+
- "8081:8081"

docker/app/Dockerfile

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
FROM python:2-slim
2+
3+
RUN apt-get update \
4+
# dependencies for building Python packages
5+
&& apt-get install -y build-essential \
6+
&& apt-get install -y python-dev \
7+
&& apt-get install -y wget \
8+
&& apt-get install -y zip unzip
9+
10+
WORKDIR /usr/src/app
11+
12+
COPY requirements ./requirements
13+
COPY ./docker/app/run.sh /run.sh
14+
15+
RUN pip install -r requirements/requirements.txt -t lib/
16+
RUN pip install -r requirements/local_requirements.txt
17+
18+
# Install App engine SDK
19+
RUN wget https://storage.googleapis.com/appengine-sdks/featured/google_appengine_1.9.90.zip -nv -P /usr/src/
20+
RUN unzip -q /usr/src/google_appengine_1.9.90.zip -d /usr/src/
21+
ENV SDK_LOCATION="/usr/src/google_appengine"
22+
23+
# Install Google Chrome for running tests
24+
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub -P /usr/src/ | apt-key add -
25+
RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list'
26+
RUN apt-get -y update
27+
RUN apt-get install -y google-chrome-stable
28+
29+
# Set display port to avoid crash
30+
ENV DISPLAY=:99
31+
32+
COPY . .
33+
34+
# Install chromedriver
35+
RUN wget https://chromedriver.storage.googleapis.com/81.0.4044.69/chromedriver_linux64.zip -P /usr/src/
36+
RUN unzip -q /usr/src/chromedriver_linux64.zip -d /usr/local/bin/
37+
38+
ENTRYPOINT [ "/run.sh" ]

docker/app/run.sh

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/usr/bin/env bash
2+
3+
HOST="0.0.0.0"
4+
API_PORT="8082"
5+
ADMIN_PORT="8083"
6+
DATASTORE_EMULATOR_HOST_PORT=datastore:8081
7+
8+
python $SDK_LOCATION/dev_appserver.py --api_host 0.0.0.0 \
9+
--api_port "$API_PORT" \
10+
--admin_host "$HOST" \
11+
--admin_port "$ADMIN_PORT" \
12+
--host "$HOST" \
13+
--skip_sdk_update_check 1 . \
14+
--env_var DATASTORE_EMULATOR_HOST="$DATASTORE_EMULATOR_HOST_PORT" \
15+
--env_var DATASTORE_USE_PROJECT_ID_AS_APP_ID=true

docker/datastore/Dockerfile

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
FROM google/cloud-sdk:latest
2+
3+
WORKDIR /usr/src/app
4+
COPY ./docker/datastore/run.sh ./run.sh
5+
6+
ENV CLOUDSDK_CORE_PROJECT=sympy-live-hrd
7+
8+
ENTRYPOINT [ "./run.sh" ]

docker/datastore/run.sh

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
3+
gcloud beta emulators datastore start --host-port=0.0.0.0:8081

tests/conftest.py

+4
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ def browser(config):
3737
elif config['browser'] == 'Headless Chrome':
3838
opts = selenium.webdriver.ChromeOptions()
3939
opts.add_argument('headless')
40+
opts.add_argument('--no-sandbox')
41+
opts.add_argument('--window-size=1420,1080')
42+
opts.add_argument('--disable-gpu')
43+
4044
b = selenium.webdriver.Chrome(options=opts)
4145
else:
4246
raise Exception('Browser "%s" is not supported' % config["browser"])

0 commit comments

Comments
 (0)