├── .gitignore ├── .gitlab-ci.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Pipfile ├── Pipfile.lock ├── README.md ├── app.py ├── res └── logo.xcf └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | .vscode/ 3 | 4 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: docker:latest 2 | 3 | stages: 4 | - build 5 | - test 6 | - publish 7 | 8 | variables: 9 | PIPELINE_IMAGE_NAME: registry.gitlab.com/dfederschmidt/docker-pipenv-sample:$CI_BUILD_REF_NAME 10 | RELEASE_IMAGE_NAME: registry.gitlab.com/dfederschmidt/docker-pipenv-sample:latest 11 | 12 | services: 13 | - docker:dind 14 | 15 | before_script: 16 | - docker info 17 | - docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com 18 | - apk update 19 | - apk upgrade 20 | - apk add python python-dev py-pip build-base 21 | - pip install requests 22 | 23 | build_image: 24 | stage: build 25 | script: 26 | - docker build -t $PIPELINE_IMAGE_NAME . 27 | - docker push $PIPELINE_IMAGE_NAME 28 | 29 | run_tests: 30 | stage: test 31 | script: 32 | - docker pull $PIPELINE_IMAGE_NAME 33 | - docker run -d -p 5000:5000 $PIPELINE_IMAGE_NAME python test.py 34 | 35 | push_to_registy: 36 | stage: publish 37 | only: 38 | - master 39 | script: 40 | - docker pull $PIPELINE_IMAGE_NAME 41 | - docker tag $PIPELINE_IMAGE_NAME $RELEASE_IMAGE_NAME 42 | - docker push $RELEASE_IMAGE_NAME 43 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | 6 | ## [1.0.0] 2018-06-09 7 | ### Added 8 | - Changelog 9 | - CI Configuration 10 | - Test 11 | 12 | ### Changed 13 | - README 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Feel free to open [issues](https://gitlab.com/dfederschmidt/docker-pipenv-sample/issues) / [pull requests](https://gitlab.com/dfederschmidt/docker-pipenv-sample/merge_requests) on [Gitlab](https://gitlab.com/dfederschmidt/docker-pipenv-sample). -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | from python:3 2 | 3 | MAINTAINER daniel@federschmidt.xyz 4 | 5 | COPY . /app 6 | WORKDIR /app 7 | 8 | RUN pip install pipenv 9 | 10 | RUN pipenv install --system --deploy 11 | 12 | CMD ["python", "app.py"] 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Daniel Federschmidt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | 3 | url = "https://pypi.python.org/simple" 4 | verify_ssl = true 5 | name = "pypi" 6 | 7 | 8 | [dev-packages] 9 | 10 | 11 | 12 | [packages] 13 | 14 | flask = "*" 15 | requests = "*" 16 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "49045f4595c8672a5a856faef4de45a7c333bdb405736f0be75050e9d6a26aa9" 5 | }, 6 | "host-environment-markers": { 7 | "implementation_name": "cpython", 8 | "implementation_version": "3.6.5", 9 | "os_name": "posix", 10 | "platform_machine": "x86_64", 11 | "platform_python_implementation": "CPython", 12 | "platform_release": "4.16.13-300.fc28.x86_64", 13 | "platform_system": "Linux", 14 | "platform_version": "#1 SMP Wed May 30 14:31:00 UTC 2018", 15 | "python_full_version": "3.6.5", 16 | "python_version": "3.6", 17 | "sys_platform": "linux" 18 | }, 19 | "pipfile-spec": 6, 20 | "requires": {}, 21 | "sources": [ 22 | { 23 | "name": "pypi", 24 | "url": "https://pypi.python.org/simple", 25 | "verify_ssl": true 26 | } 27 | ] 28 | }, 29 | "default": { 30 | "certifi": { 31 | "hashes": [ 32 | "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0", 33 | "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7" 34 | ], 35 | "version": "==2018.4.16" 36 | }, 37 | "chardet": { 38 | "hashes": [ 39 | "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691", 40 | "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae" 41 | ], 42 | "version": "==3.0.4" 43 | }, 44 | "click": { 45 | "hashes": [ 46 | "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", 47 | "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" 48 | ], 49 | "version": "==6.7" 50 | }, 51 | "flask": { 52 | "hashes": [ 53 | "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05", 54 | "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48" 55 | ], 56 | "version": "==1.0.2" 57 | }, 58 | "idna": { 59 | "hashes": [ 60 | "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4", 61 | "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f" 62 | ], 63 | "version": "==2.6" 64 | }, 65 | "itsdangerous": { 66 | "hashes": [ 67 | "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" 68 | ], 69 | "version": "==0.24" 70 | }, 71 | "jinja2": { 72 | "hashes": [ 73 | "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", 74 | "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" 75 | ], 76 | "version": "==2.10" 77 | }, 78 | "markupsafe": { 79 | "hashes": [ 80 | "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" 81 | ], 82 | "version": "==1.0" 83 | }, 84 | "requests": { 85 | "hashes": [ 86 | "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", 87 | "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" 88 | ], 89 | "version": "==2.18.4" 90 | }, 91 | "urllib3": { 92 | "hashes": [ 93 | "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", 94 | "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" 95 | ], 96 | "version": "==1.22" 97 | }, 98 | "werkzeug": { 99 | "hashes": [ 100 | "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b", 101 | "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c" 102 | ], 103 | "version": "==0.14.1" 104 | } 105 | }, 106 | "develop": {} 107 | } 108 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # docker-pipenv-sample 2 | 3 | This is a minimal example of using pipenv to install dependencies for a containerized Python project. 4 | 5 | ## Getting Started 6 | 7 | These instructions will get you a copy of the project up and running on your local machine for fun. 8 | If you want to use pipenv to manage your Python dependencies in your project that should run in Docker 9 | you should start with inspecting the Dockerfile in this repository. 10 | 11 | 12 | ### Prerequisites 13 | 14 | * **Docker**: If you still need to install this, you might want to check out [the Docker documentation](https://docs.docker.com/install/). 15 | 16 | 17 | ### Building from source 18 | 19 | 1. Get a local copy of the repository and navigate to the project directory. 20 | 21 | 2. Inside the project directory, run the command below. This will build the image. 22 | ```bash 23 | docker build -t docker-pipenv-sample . 24 | ``` 25 | 26 | 3. Run a container based on the image. 27 | ```bash 28 | docker run -p 5000:5000 docker-pipenv-sample 29 | ``` 30 | 31 | 4. Use [Pipenv](https://github.com/pypa/pipenv) to manage your Python dependencies from now on with it. Please. 32 | 33 | 5. Read the Dockerfile and see how easy it is to adapt it for your project. 34 | 35 | ### Building from Container Registry 36 | 37 | You can also get a pre-built image from the [Gitlab Container Registry](https://gitlab.com/dfederschmidt/docker-pipenv-sample/container_registry). But where is the fun in that? 38 | 39 | ```bash 40 | docker run -p 5000:5000 registry.gitlab.com/dfederschmidt/docker-pipenv-sample:latest 41 | ``` 42 | 43 | ## Running tests 44 | 45 | To run the test locally use the command below. 46 | 47 | ```bash 48 | pipenv install 49 | python tests.py 50 | ``` 51 | 52 | It also runs on every new change as part of a [Gitlab CI/CD pipeline](https://gitlab.com/dfederschmidt/docker-pipenv-sample/pipelines). 53 | 54 | ## Built With 55 | 56 | * [Docker](https://www.docker.com/what-docker) 57 | * [Pipenv](https://docs.pipenv.org/) 58 | * [Flask](http://flask.pocoo.org/) 59 | 60 | ## Contributing 61 | 62 | Feel free to open [issues](https://gitlab.com/dfederschmidt/docker-pipenv-sample/issues) / [pull requests](https://gitlab.com/dfederschmidt/docker-pipenv-sample/merge_requests) on [Gitlab](https://gitlab.com/dfederschmidt/docker-pipenv-sample). 63 | 64 | ## Versioning 65 | 66 | [Changelog](https://gitlab.com/dfederschmidt/docker-pipenv-sample/blob/master/CHANGELOG) can be found on Gitlab. 67 | 68 | [SemVer](https://semver.org/). See [repository tags](https://gitlab.com/dfederschmidt/docker-pipenv-sample). 69 | 70 | 71 | ## Authors 72 | 73 | * **Daniel Federschmidt** - *all the things* - [federschmidt.xyz](https://federschmidt.xyz) 74 | 75 | ## Acknowledgments 76 | 77 | * [Kenneth Reitz](https://www.kennethreitz.org/) for conceiving Pipenv - awesome tool :cake:. 78 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | """ This is a very basic flask server""" 2 | from flask import Flask 3 | 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route("/") 8 | def hello(): 9 | """docstring""" 10 | return "Hello World!" 11 | 12 | 13 | if __name__ == '__main__': 14 | app.run(host="0.0.0.0", debug = True) 15 | -------------------------------------------------------------------------------- /res/logo.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dfederschmidt/docker-pipenv-sample/129f1be516482554cf214e70095b75bc36cac57c/res/logo.xcf -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import requests as r 3 | import sys 4 | 5 | class WebServerTests(unittest.TestCase): 6 | 7 | def test_webserver_accessible(self): 8 | res = r.get("http://localhost:5000") 9 | self.assertTrue(res.text, "Hello World!") 10 | 11 | if __name__ == '__main__': 12 | unittest.main() --------------------------------------------------------------------------------