Skip to content

Commit 0ea703b

Browse files
committed
Release 0.1
1 parent 45f562b commit 0ea703b

12 files changed

+492
-1
lines changed

.env.example

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
###
2+
### Flask settings
3+
###
4+
5+
# Name of the entrypoint file
6+
FLASK_APP=main.py
7+
8+
# Name of the project directory which is mounted
9+
# to /shared/httpd into the container
10+
FLASK_PROJECT=test-project
11+
12+
# Docker container internal port
13+
FLASK_PORT=3000
14+
15+
# What Python image to choose
16+
PYTHON_VERSION=3.8
17+
18+
19+
###
20+
### File permission settings
21+
###
22+
23+
# uid/gid of local user for permission syncronization
24+
NEW_GID=1000
25+
NEW_UID=1000
26+
27+
28+
###
29+
### Host system settings
30+
###
31+
32+
# Expose application on this port to host system
33+
HOST_PORT_FLASK=3000

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.pyc
2+
.env
3+
/test-project/venv
4+
/test-project/app/__pycache__

.tests/test-project.sh

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
set -u
5+
set -o pipefail
6+
7+
TEST_PATH="$( cd "$(dirname "$0")" && pwd -P )"
8+
ROOT_PATH="$( cd "${TEST_PATH}/.." && pwd -P )"
9+
10+
retry() {
11+
for ((n=0; n<20; n++)); do
12+
echo "[${n}] ${*}"
13+
if eval "${*}"; then
14+
return 0
15+
fi
16+
sleep 1
17+
done
18+
return 1
19+
}
20+
21+
IMAGE="${1}"
22+
PYTHON="${2}"
23+
24+
# -------------------------------------------------------------------------------------------------
25+
# Clean environment
26+
# -------------------------------------------------------------------------------------------------
27+
rm -rf "${ROOT_PATH}/test-project/venv"
28+
rm -rf "${ROOT_PATH}/test-project/app/__pycache__"
29+
30+
31+
echo
32+
echo "# -------------------------------------------------------------------------------------------------"
33+
echo "# Test Container"
34+
echo "# -------------------------------------------------------------------------------------------------"
35+
echo
36+
37+
NAME="devilbox-python-flask-${PYTHON}"
38+
39+
docker run --rm -d \
40+
--name "${NAME}" \
41+
-v "${ROOT_PATH}/test-project:/shared/httpd/test-project" \
42+
-p "3000:3000" \
43+
-e NEW_UID="$(id -u)" \
44+
-e NEW_GID="$(id -g)" \
45+
-e FLASK_PROJECT="test-project" \
46+
"${IMAGE}:${PYTHON}-dev"
47+
48+
if ! retry curl -sS 'http://localhost:3000' | grep 'Hello World'; then
49+
docker ps -a --no-trunc || true
50+
docker logs "${NAME}" || true
51+
docker stop "${NAME}" >/dev/null 2>&1 || true
52+
docker rm -f "${NAME}" >/dev/null 2>&1 || true
53+
54+
# Start in with log output to see what happens
55+
docker run --rm \
56+
--name "${NAME}" \
57+
-v "${ROOT_PATH}/test-project:/shared/httpd/test-project" \
58+
-p "3000:3000" \
59+
-e FLASK_PROJECT="test-project" \
60+
-e NEW_UID="$(id -u)" \
61+
-e NEW_GID="$(id -g)" \
62+
"${IMAGE}:${PYTHON}-dev" &
63+
sleep 20
64+
docker stop "${NAME}" >/dev/null 2>&1 || true
65+
docker rm -f "${NAME}" >/dev/null 2>&1 || true
66+
exit 1
67+
fi
68+
69+
docker logs "${NAME}"
70+
docker stop "${NAME}" || true
71+
docker rm -f "${NAME}" >/dev/null 2>&1 || true
72+
73+
74+
echo
75+
echo "# -------------------------------------------------------------------------------------------------"
76+
echo "# Test Docker Compose"
77+
echo "# -------------------------------------------------------------------------------------------------"
78+
echo
79+
cp -f "${ROOT_PATH}/.env.example" "${ROOT_PATH}/.env"
80+
sed -i'' "s/^PYTHON_VERSION=.*/PYTHON_VERSION=${PYTHON}/g" "${ROOT_PATH}/.env"
81+
sed -i'' "s/^NEW_UID=.*/NEW_UID=$(id -u)/g" "${ROOT_PATH}/.env"
82+
sed -i'' "s/^NEW_GID=.*/NEW_GID=$(id -g)/g" "${ROOT_PATH}/.env"
83+
84+
cd "${ROOT_PATH}"
85+
docker-compose up -d
86+
87+
88+
if ! retry curl -sS 'http://localhost:3000' | grep 'Hello World'; then
89+
docker ps -a --no-trunc || true
90+
docker-compose logs || true
91+
docker-compose stop >/dev/null 2>&1 || true
92+
docker-compose rm -f >/dev/null 2>&1 || true
93+
94+
# Start in with log output to see what happens
95+
docker-compose up &
96+
sleep 20
97+
docker-compose stop >/dev/null 2>&1 || true
98+
docker-compose rm -f >/dev/null 2>&1 || true
99+
exit 1
100+
fi
101+
102+
docker-compose logs
103+
docker-compose stop || true
104+
docker-compose rm -f >/dev/null 2>&1 || true

.travis.yml

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
3+
###
4+
### Travis settings
5+
###
6+
sudo: required
7+
language: minimal
8+
services:
9+
- docker
10+
11+
12+
###
13+
### Build Matrix
14+
###
15+
env:
16+
matrix:
17+
- PYTHON=3.8
18+
- PYTHON=3.7
19+
- PYTHON=3.6
20+
- PYTHON=3.5
21+
- PYTHON=2.7
22+
23+
24+
###
25+
### Install requirements
26+
###
27+
install:
28+
- docker version
29+
- netstat -tulpn
30+
31+
- retry() {
32+
for ((n=0; n<10; n++)); do
33+
echo "[${n}] ${*}";
34+
if eval "${*}"; then
35+
return 0;
36+
fi;
37+
sleep 1;
38+
done;
39+
return 1;
40+
}
41+
42+
43+
###
44+
### Check generation changes, build and test
45+
###
46+
before_script:
47+
- retry make build PYTHON=${PYTHON}
48+
- retry make test PYTHON=${PYTHON}
49+
50+
51+
###
52+
### Push to Dockerhub
53+
###
54+
script:
55+
# Push to docker hub on success
56+
- if [ "${TRAVIS_PULL_REQUEST}" == "false" ]; then
57+
retry make login USER="${DOCKER_USERNAME}" PASS="${DOCKER_PASSWORD}";
58+
if [ -n "${TRAVIS_TAG}" ]; then
59+
retry make push TAG="${PYTHON}-dev-${TRAVIS_TAG}";
60+
elif [ "${TRAVIS_BRANCH}" == "master" ]; then
61+
retry make push TAG="${PYTHON}-dev";
62+
elif [[ ${TRAVIS_BRANCH} =~ ^(release-[.0-9]+.*)$ ]]; then
63+
retry make push TAG="${PYTHON}-dev-${TRAVIS_BRANCH}";
64+
else
65+
echo "Skipping branch ${TRAVIS_BRANCH}";
66+
fi
67+
else
68+
echo "Skipping push on PR";
69+
fi

Dockerfile

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
###
2+
### BUILDER
3+
###
4+
ARG ALPINE
5+
ARG PYTHON
6+
FROM python:${PYTHON}-alpine${ALPINE} as builder-dev
7+
8+
# General requirements
9+
RUN set -x \
10+
&& apk add --no-cache \
11+
gcc \
12+
musl-dev \
13+
linux-headers
14+
15+
RUN set -x \
16+
&& pip install \
17+
flask \
18+
virtualenv
19+
20+
21+
###
22+
### DEVELOPMENT
23+
###
24+
FROM python:${PYTHON}-alpine${ALPINE} as dev
25+
ARG PYTHON
26+
27+
# Labels
28+
# https://github.com/opencontainers/image-spec/blob/master/annotations.md
29+
#LABEL "org.opencontainers.image.created"=""
30+
#LABEL "org.opencontainers.image.version"=""
31+
#LABEL "org.opencontainers.image.revision"=""
32+
LABEL "maintainer"="cytopia <[email protected]>"
33+
LABEL "org.opencontainers.image.authors"="cytopia <[email protected]>"
34+
LABEL "org.opencontainers.image.url"="https://github.com/devilbox/docker-python-flask"
35+
LABEL "org.opencontainers.image.documentation"="https://github.com/devilbox/docker-python-flask"
36+
LABEL "org.opencontainers.image.source"="https://github.com/devilbox/docker-python-flask"
37+
LABEL "org.opencontainers.image.vendor"="devilbox"
38+
LABEL "org.opencontainers.image.licenses"="MIT"
39+
LABEL "org.opencontainers.image.ref.name"="${PYTHON}-dev"
40+
LABEL "org.opencontainers.image.title"="Python ${PYTHON}-dev"
41+
LABEL "org.opencontainers.image.description"="Python ${PYTHON}-dev"
42+
43+
# Copy artifacts from builder
44+
COPY --from=builder-dev /usr/local/lib/python${PYTHON}/site-packages/ /usr/local/lib/python${PYTHON}/site-packages/
45+
COPY --from=builder-dev /usr/local/bin/flask /usr/local/bin/flask
46+
COPY --from=builder-dev /usr/local/bin/virtualenv /usr/local/bin/virtualenv
47+
48+
# Build args
49+
ARG UID=1000
50+
ARG GID=1000
51+
52+
# User
53+
RUN set -x \
54+
&& addgroup -g ${GID} devilbox \
55+
&& adduser -h /home/devilbox -G devilbox -D -u ${UID} devilbox
56+
57+
# Start script
58+
ENV NEW_UID=${UID}
59+
ENV NEW_GID=${GID}
60+
COPY data/start.sh /start.sh
61+
62+
# Start
63+
CMD ["/start.sh"]

Makefile

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
ifneq (,)
2+
.error This Makefile requires GNU Make.
3+
endif
4+
5+
# -------------------------------------------------------------------------------------------------
6+
# Default configuration
7+
# -------------------------------------------------------------------------------------------------
8+
.PHONY: build
9+
10+
11+
# -------------------------------------------------------------------------------------------------
12+
# Docker configuration
13+
# -------------------------------------------------------------------------------------------------
14+
DIR = .
15+
FILE = Dockerfile
16+
IMAGE = devilbox/python-flask
17+
NO_CACHE =
18+
PYTHON = 3.8
19+
20+
21+
# -------------------------------------------------------------------------------------------------
22+
# Default target
23+
# -------------------------------------------------------------------------------------------------
24+
help:
25+
@echo "build Build Docker image"
26+
@echo "test Test Docker image"
27+
28+
29+
# -------------------------------------------------------------------------------------------------
30+
# Common Targets
31+
# -------------------------------------------------------------------------------------------------
32+
build:
33+
docker build \
34+
--label "org.opencontainers.image.created"="$$(date --rfc-3339=s)" \
35+
--label "org.opencontainers.image.revision"="$$(git rev-parse HEAD)" \
36+
--label "org.opencontainers.image.version"="$(PYTHON)-dev" \
37+
--target dev \
38+
--build-arg ALPINE= \
39+
--build-arg PYTHON=$(PYTHON) \
40+
-t $(IMAGE) \
41+
-f $(DIR)/Dockerfile $(DIR)
42+
@$(MAKE) --no-print-directory tag TAG=$(PYTHON)-dev
43+
44+
45+
test:
46+
docker run --rm $(IMAGE):$(PYTHON)-dev python --version 2>&1 | grep -E 'Python $(PYTHON)[.0-9]+'
47+
.tests/test-project.sh "$(IMAGE)" "$(PYTHON)"
48+
49+
50+
# -------------------------------------------------------------------------------------------------
51+
# CI Targets
52+
# -------------------------------------------------------------------------------------------------
53+
tag:
54+
@if [ "$(TAG)" = "" ]; then \
55+
>&2 echo "Error, you must specify TAG=..."; \
56+
exit 1; \
57+
fi
58+
docker tag $(IMAGE) $(IMAGE):$(TAG)
59+
docker images "$(IMAGE)"
60+
61+
62+
login:
63+
yes | docker login --username $(USER) --password $(PASS)
64+
65+
66+
push: tag
67+
docker push $(IMAGE):$(TAG)

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Python Flask Docker image
22

3-
[![Build Status](https://travis-ci.org/devilbox/docker-python-flask.svg?branch=master)](https://travis-ci.org/devilbox/docker-python-flask)
3+
[![Build Status](https://travis-ci.com/devilbox/docker-python-flask.svg?branch=master)](https://travis-ci.com/devilbox/docker-python-flask)
44
[![Tag](https://img.shields.io/github/tag/devilbox/docker-python-flask.svg)](https://github.com/devilbox/docker-python-flask/releases)
55
[![Gitter](https://badges.gitter.im/devilbox/Lobby.svg)](https://gitter.im/devilbox/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
66
[![Discourse](https://img.shields.io/discourse/https/devilbox.discourse.group/status.svg?colorB=%234CB697)](https://devilbox.discourse.group)

0 commit comments

Comments
 (0)